MAJOR: connection: move the addr field from the stream_interface

We need to have the source and destination addresses in the connection.
They were lying in the stream interface so let's move them. The flags
SI_FL_FROM_SET and SI_FL_TO_SET have been moved as well.

It's worth noting that tcp_connect_server() almost does not use the
stream interface anymore except for a few flags.

It has been identified that once we detach the connection from the SI,
it will probably be needed to keep a copy of the server-side addresses
in the SI just for logging purposes. This has not been implemented right
now though.
diff --git a/src/backend.c b/src/backend.c
index 845c93b..3cb10fe 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -547,14 +547,14 @@
 
 			switch (s->be->lbprm.algo & BE_LB_PARM) {
 			case BE_LB_HASH_SRC:
-				if (s->req->prod->addr.from.ss_family == AF_INET) {
+				if (s->req->prod->conn.addr.from.ss_family == AF_INET) {
 					srv = get_server_sh(s->be,
-							    (void *)&((struct sockaddr_in *)&s->req->prod->addr.from)->sin_addr,
+							    (void *)&((struct sockaddr_in *)&s->req->prod->conn.addr.from)->sin_addr,
 							    4);
 				}
-				else if (s->req->prod->addr.from.ss_family == AF_INET6) {
+				else if (s->req->prod->conn.addr.from.ss_family == AF_INET6) {
 					srv = get_server_sh(s->be,
-							    (void *)&((struct sockaddr_in6 *)&s->req->prod->addr.from)->sin6_addr,
+							    (void *)&((struct sockaddr_in6 *)&s->req->prod->conn.addr.from)->sin6_addr,
 							    16);
 				}
 				else {
@@ -637,7 +637,7 @@
 		set_target_proxy(&s->target, s->be);
 	}
 	else if ((s->be->options & PR_O_HTTP_PROXY) &&
-		 is_addr(&s->req->cons->addr.to)) {
+		 is_addr(&s->req->cons->conn.addr.to)) {
 		/* in proxy mode, we need a valid destination address */
 		set_target_proxy(&s->target, s->be);
 	}
@@ -691,20 +691,20 @@
 		if (!(s->flags & SN_ASSIGNED))
 			return SRV_STATUS_INTERNAL;
 
-		s->req->cons->addr.to = target_srv(&s->target)->addr;
+		s->req->cons->conn.addr.to = target_srv(&s->target)->addr;
 
-		if (!is_addr(&s->req->cons->addr.to)) {
+		if (!is_addr(&s->req->cons->conn.addr.to)) {
 			/* 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.
 			 */
 			if (!(s->be->options & PR_O_TRANSP))
-				si_get_to_addr(s->req->prod);
+				conn_get_to_addr(&s->req->prod->conn);
 
-			if (s->req->prod->addr.to.ss_family == AF_INET) {
-				((struct sockaddr_in *)&s->req->cons->addr.to)->sin_addr = ((struct sockaddr_in *)&s->req->prod->addr.to)->sin_addr;
-			} else if (s->req->prod->addr.to.ss_family == AF_INET6) {
-				((struct sockaddr_in6 *)&s->req->cons->addr.to)->sin6_addr = ((struct sockaddr_in6 *)&s->req->prod->addr.to)->sin6_addr;
+			if (s->req->prod->conn.addr.to.ss_family == AF_INET) {
+				((struct sockaddr_in *)&s->req->cons->conn.addr.to)->sin_addr = ((struct sockaddr_in *)&s->req->prod->conn.addr.to)->sin_addr;
+			} else if (s->req->prod->conn.addr.to.ss_family == AF_INET6) {
+				((struct sockaddr_in6 *)&s->req->cons->conn.addr.to)->sin6_addr = ((struct sockaddr_in6 *)&s->req->prod->conn.addr.to)->sin6_addr;
 			}
 		}
 
@@ -714,26 +714,26 @@
 			int base_port;
 
 			if (!(s->be->options & PR_O_TRANSP))
-				si_get_to_addr(s->req->prod);
+				conn_get_to_addr(&s->req->prod->conn);
 
 			/* First, retrieve the port from the incoming connection */
-			base_port = get_host_port(&s->req->prod->addr.to);
+			base_port = get_host_port(&s->req->prod->conn.addr.to);
 
 			/* Second, assign the outgoing connection's port */
-			base_port += get_host_port(&s->req->cons->addr.to);
-			set_host_port(&s->req->cons->addr.to, base_port);
+			base_port += get_host_port(&s->req->cons->conn.addr.to);
+			set_host_port(&s->req->cons->conn.addr.to, base_port);
 		}
 	}
 	else if (s->be->options & PR_O_DISPATCH) {
 		/* connect to the defined dispatch addr */
-		s->req->cons->addr.to = s->be->dispatch_addr;
+		s->req->cons->conn.addr.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 */
-		si_get_to_addr(s->req->prod);
+		conn_get_to_addr(&s->req->prod->conn);
 
-		if (s->req->prod->addr.to.ss_family == AF_INET || s->req->prod->addr.to.ss_family == AF_INET6) {
-			memcpy(&s->req->cons->addr.to, &s->req->prod->addr.to, MIN(sizeof(s->req->cons->addr.to), sizeof(s->req->prod->addr.to)));
+		if (s->req->prod->conn.addr.to.ss_family == AF_INET || s->req->prod->conn.addr.to.ss_family == AF_INET6) {
+			memcpy(&s->req->cons->conn.addr.to, &s->req->prod->conn.addr.to, MIN(sizeof(s->req->cons->conn.addr.to), sizeof(s->req->prod->conn.addr.to)));
 		}
 		/* when we support IPv6 on the backend, we may add other tests */
 		//qfprintf(stderr, "Cannot get original server address.\n");
@@ -887,12 +887,12 @@
 	if (srv && srv->state & SRV_BIND_SRC) {
 		switch (srv->state & SRV_TPROXY_MASK) {
 		case SRV_TPROXY_ADDR:
-			s->req->cons->addr.from = srv->tproxy_addr;
+			s->req->cons->conn.addr.from = 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->req->cons->addr.from = s->req->prod->addr.from;
+			s->req->cons->conn.addr.from = s->req->prod->conn.addr.from;
 			break;
 		case SRV_TPROXY_DYN:
 			if (srv->bind_hdr_occ) {
@@ -901,32 +901,32 @@
 				int rewind;
 
 				/* bind to the IP in a header */
-				((struct sockaddr_in *)&s->req->cons->addr.from)->sin_family = AF_INET;
-				((struct sockaddr_in *)&s->req->cons->addr.from)->sin_port = 0;
-				((struct sockaddr_in *)&s->req->cons->addr.from)->sin_addr.s_addr = 0;
+				((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_family = AF_INET;
+				((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_port = 0;
+				((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_addr.s_addr = 0;
 
 				b_rew(&s->req->buf, rewind = s->req->buf.o);
 				if (http_get_hdr(&s->txn.req, srv->bind_hdr_name, srv->bind_hdr_len,
 						 &s->txn.hdr_idx, srv->bind_hdr_occ, NULL, &vptr, &vlen)) {
-					((struct sockaddr_in *)&s->req->cons->addr.from)->sin_addr.s_addr =
+					((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_addr.s_addr =
 						htonl(inetaddr_host_lim(vptr, vptr + vlen));
 				}
 				b_adv(&s->req->buf, rewind);
 			}
 			break;
 		default:
-			memset(&s->req->cons->addr.from, 0, sizeof(s->req->cons->addr.from));
+			memset(&s->req->cons->conn.addr.from, 0, sizeof(s->req->cons->conn.addr.from));
 		}
 	}
 	else if (s->be->options & PR_O_BIND_SRC) {
 		switch (s->be->options & PR_O_TPXY_MASK) {
 		case PR_O_TPXY_ADDR:
-			s->req->cons->addr.from = s->be->tproxy_addr;
+			s->req->cons->conn.addr.from = 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->req->cons->addr.from = s->req->prod->addr.from;
+			s->req->cons->conn.addr.from = s->req->prod->conn.addr.from;
 			break;
 		case PR_O_TPXY_DYN:
 			if (s->be->bind_hdr_occ) {
@@ -935,21 +935,21 @@
 				int rewind;
 
 				/* bind to the IP in a header */
-				((struct sockaddr_in *)&s->req->cons->addr.from)->sin_family = AF_INET;
-				((struct sockaddr_in *)&s->req->cons->addr.from)->sin_port = 0;
-				((struct sockaddr_in *)&s->req->cons->addr.from)->sin_addr.s_addr = 0;
+				((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_family = AF_INET;
+				((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_port = 0;
+				((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_addr.s_addr = 0;
 
 				b_rew(&s->req->buf, rewind = s->req->buf.o);
 				if (http_get_hdr(&s->txn.req, s->be->bind_hdr_name, s->be->bind_hdr_len,
 						 &s->txn.hdr_idx, s->be->bind_hdr_occ, NULL, &vptr, &vlen)) {
-					((struct sockaddr_in *)&s->req->cons->addr.from)->sin_addr.s_addr =
+					((struct sockaddr_in *)&s->req->cons->conn.addr.from)->sin_addr.s_addr =
 						htonl(inetaddr_host_lim(vptr, vptr + vlen));
 				}
 				b_adv(&s->req->buf, rewind);
 			}
 			break;
 		default:
-			memset(&s->req->cons->addr.from, 0, sizeof(s->req->cons->addr.from));
+			memset(&s->req->cons->conn.addr.from, 0, sizeof(s->req->cons->conn.addr.from));
 		}
 	}
 #endif
@@ -989,7 +989,7 @@
 	}
 	else if (s->target.type == TARG_TYPE_PROXY) {
 		/* proxies exclusively run on raw_sock right now */
-		si_prepare_conn(s->req->cons, protocol_by_family(s->req->cons->addr.to.ss_family), &raw_sock);
+		si_prepare_conn(s->req->cons, protocol_by_family(s->req->cons->conn.addr.to.ss_family), &raw_sock);
 		if (!si_ctrl(s->req->cons))
 			return SN_ERR_INTERNAL;
 	}
@@ -1000,7 +1000,7 @@
 	s->req->cons->send_proxy_ofs = 0;
 	if (s->target.type == TARG_TYPE_SERVER && (s->target.ptr.s->state & SRV_SEND_PROXY)) {
 		s->req->cons->send_proxy_ofs = 1; /* must compute size */
-		si_get_to_addr(s->req->prod);
+		conn_get_to_addr(&s->req->prod->conn);
 	}
 
 	assign_tproxy_address(s);
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 7728616..2e775d9 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -3330,11 +3330,11 @@
 			     sess->uniq_id,
 			     sess->listener->proto->name);
 
-		switch (addr_to_str(&sess->si[0].addr.from, pn, sizeof(pn))) {
+		switch (addr_to_str(&sess->si[0].conn.addr.from, pn, sizeof(pn))) {
 		case AF_INET:
 		case AF_INET6:
 			chunk_printf(&msg, " source=%s:%d\n",
-				     pn, get_host_port(&sess->si[0].addr.from));
+				     pn, get_host_port(&sess->si[0].conn.addr.from));
 			break;
 		case AF_UNIX:
 			chunk_printf(&msg, " source=unix:%d\n", sess->listener->luid);
@@ -3355,12 +3355,12 @@
 			     sess->listener ? sess->listener->name ? sess->listener->name : "?" : "?",
 			     sess->listener ? sess->listener->luid : 0);
 
-		si_get_to_addr(&sess->si[0]);
-		switch (addr_to_str(&sess->si[0].addr.to, pn, sizeof(pn))) {
+		conn_get_to_addr(&sess->si[0].conn);
+		switch (addr_to_str(&sess->si[0].conn.addr.to, pn, sizeof(pn))) {
 		case AF_INET:
 		case AF_INET6:
 			chunk_printf(&msg, " addr=%s:%d\n",
-				     pn, get_host_port(&sess->si[0].addr.to));
+				     pn, get_host_port(&sess->si[0].conn.addr.to));
 			break;
 		case AF_UNIX:
 			chunk_printf(&msg, " addr=unix:%d\n", sess->listener->luid);
@@ -3379,12 +3379,12 @@
 		else
 			chunk_printf(&msg, "  backend=<NONE> (id=-1 mode=-)");
 
-		si_get_from_addr(&sess->si[1]);
-		switch (addr_to_str(&sess->si[1].addr.from, pn, sizeof(pn))) {
+		conn_get_from_addr(&sess->si[1].conn);
+		switch (addr_to_str(&sess->si[1].conn.addr.from, pn, sizeof(pn))) {
 		case AF_INET:
 		case AF_INET6:
 			chunk_printf(&msg, " addr=%s:%d\n",
-				     pn, get_host_port(&sess->si[1].addr.from));
+				     pn, get_host_port(&sess->si[1].conn.addr.from));
 			break;
 		case AF_UNIX:
 			chunk_printf(&msg, " addr=unix\n");
@@ -3403,12 +3403,12 @@
 		else
 			chunk_printf(&msg, "  server=<NONE> (id=-1)");
 
-		si_get_to_addr(&sess->si[1]);
-		switch (addr_to_str(&sess->si[1].addr.to, pn, sizeof(pn))) {
+		conn_get_to_addr(&sess->si[1].conn);
+		switch (addr_to_str(&sess->si[1].conn.addr.to, pn, sizeof(pn))) {
 		case AF_INET:
 		case AF_INET6:
 			chunk_printf(&msg, " addr=%s:%d\n",
-				     pn, get_host_port(&sess->si[1].addr.to));
+				     pn, get_host_port(&sess->si[1].conn.addr.to));
 			break;
 		case AF_UNIX:
 			chunk_printf(&msg, " addr=unix\n");
@@ -3610,13 +3610,13 @@
 				     curr_sess->listener->proto->name);
 
 
-			switch (addr_to_str(&curr_sess->si[0].addr.from, pn, sizeof(pn))) {
+			switch (addr_to_str(&curr_sess->si[0].conn.addr.from, pn, sizeof(pn))) {
 			case AF_INET:
 			case AF_INET6:
 				chunk_printf(&msg,
 					     " src=%s:%d fe=%s be=%s srv=%s",
 					     pn,
-					     get_host_port(&curr_sess->si[0].addr.from),
+					     get_host_port(&curr_sess->si[0].conn.addr.from),
 					     curr_sess->fe->id,
 					     (curr_sess->be->cap & PR_CAP_BE) ? curr_sess->be->id : "<NONE>",
 					     target_srv(&curr_sess->target) ? target_srv(&curr_sess->target)->id : "<none>"
diff --git a/src/frontend.c b/src/frontend.c
index 8b16836..415960a 100644
--- a/src/frontend.c
+++ b/src/frontend.c
@@ -139,16 +139,16 @@
 		else {
 			char pn[INET6_ADDRSTRLEN], sn[INET6_ADDRSTRLEN];
 
-			si_get_from_addr(s->req->prod);
-			si_get_to_addr(s->req->prod);
+			conn_get_from_addr(&s->req->prod->conn);
+			conn_get_to_addr(&s->req->prod->conn);
 
-			switch (addr_to_str(&s->req->prod->addr.from, pn, sizeof(pn))) {
+			switch (addr_to_str(&s->req->prod->conn.addr.from, pn, sizeof(pn))) {
 			case AF_INET:
 			case AF_INET6:
-				addr_to_str(&s->req->prod->addr.to, sn, sizeof(sn));
+				addr_to_str(&s->req->prod->conn.addr.to, sn, sizeof(sn));
 				send_log(s->fe, LOG_INFO, "Connect from %s:%d to %s:%d (%s/%s)\n",
-					 pn, get_host_port(&s->req->prod->addr.from),
-					 sn, get_host_port(&s->req->prod->addr.to),
+					 pn, get_host_port(&s->req->prod->conn.addr.from),
+					 sn, get_host_port(&s->req->prod->conn.addr.to),
 					 s->fe->id, (s->fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP");
 				break;
 			case AF_UNIX:
@@ -165,14 +165,14 @@
 		char pn[INET6_ADDRSTRLEN];
 		int len = 0;
 
-		si_get_from_addr(s->req->prod);
+		conn_get_from_addr(&s->req->prod->conn);
 
-		switch (addr_to_str(&s->req->prod->addr.from, pn, sizeof(pn))) {
+		switch (addr_to_str(&s->req->prod->conn.addr.from, pn, sizeof(pn))) {
 		case AF_INET:
 		case AF_INET6:
 			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, get_host_port(&s->req->prod->addr.from));
+				      pn, get_host_port(&s->req->prod->conn.addr.from));
 			break;
 		case AF_UNIX:
 			/* UNIX socket, only the destination is known */
@@ -313,14 +313,14 @@
 			goto fail;
 
 		/* update the session's addresses and mark them set */
-		((struct sockaddr_in *)&s->si[0].addr.from)->sin_family      = AF_INET;
-		((struct sockaddr_in *)&s->si[0].addr.from)->sin_addr.s_addr = htonl(src3);
-		((struct sockaddr_in *)&s->si[0].addr.from)->sin_port        = htons(sport);
+		((struct sockaddr_in *)&s->si[0].conn.addr.from)->sin_family      = AF_INET;
+		((struct sockaddr_in *)&s->si[0].conn.addr.from)->sin_addr.s_addr = htonl(src3);
+		((struct sockaddr_in *)&s->si[0].conn.addr.from)->sin_port        = htons(sport);
 
-		((struct sockaddr_in *)&s->si[0].addr.to)->sin_family      = AF_INET;
-		((struct sockaddr_in *)&s->si[0].addr.to)->sin_addr.s_addr = htonl(dst3);
-		((struct sockaddr_in *)&s->si[0].addr.to)->sin_port        = htons(dport);
-		s->si[0].flags |= SI_FL_FROM_SET | SI_FL_TO_SET;
+		((struct sockaddr_in *)&s->si[0].conn.addr.to)->sin_family      = AF_INET;
+		((struct sockaddr_in *)&s->si[0].conn.addr.to)->sin_addr.s_addr = htonl(dst3);
+		((struct sockaddr_in *)&s->si[0].conn.addr.to)->sin_port        = htons(dport);
+		s->si[0].conn.flags |= CO_FL_ADDR_FROM_SET | CO_FL_ADDR_TO_SET;
 	}
 	else if (!memcmp(line, "TCP6 ", 5) != 0) {
 		u32 sport, dport;
@@ -374,14 +374,14 @@
 			goto fail;
 
 		/* update the session's addresses and mark them set */
-		((struct sockaddr_in6 *)&s->si[0].addr.from)->sin6_family      = AF_INET6;
-		memcpy(&((struct sockaddr_in6 *)&s->si[0].addr.from)->sin6_addr, &src3, sizeof(struct in6_addr));
-		((struct sockaddr_in6 *)&s->si[0].addr.from)->sin6_port        = htons(sport);
+		((struct sockaddr_in6 *)&s->si[0].conn.addr.from)->sin6_family      = AF_INET6;
+		memcpy(&((struct sockaddr_in6 *)&s->si[0].conn.addr.from)->sin6_addr, &src3, sizeof(struct in6_addr));
+		((struct sockaddr_in6 *)&s->si[0].conn.addr.from)->sin6_port        = htons(sport);
 
-		((struct sockaddr_in6 *)&s->si[0].addr.to)->sin6_family      = AF_INET6;
-		memcpy(&((struct sockaddr_in6 *)&s->si[0].addr.to)->sin6_addr, &dst3, sizeof(struct in6_addr));
-		((struct sockaddr_in6 *)&s->si[0].addr.to)->sin6_port        = htons(dport);
-		s->si[0].flags |= SI_FL_FROM_SET | SI_FL_TO_SET;
+		((struct sockaddr_in6 *)&s->si[0].conn.addr.to)->sin6_family      = AF_INET6;
+		memcpy(&((struct sockaddr_in6 *)&s->si[0].conn.addr.to)->sin6_addr, &dst3, sizeof(struct in6_addr));
+		((struct sockaddr_in6 *)&s->si[0].conn.addr.to)->sin6_port        = htons(dport);
+		s->si[0].conn.flags |= CO_FL_ADDR_FROM_SET | CO_FL_ADDR_TO_SET;
 	}
 	else {
 		goto fail;
diff --git a/src/log.c b/src/log.c
index bdb0060..2d33856 100644
--- a/src/log.c
+++ b/src/log.c
@@ -836,7 +836,7 @@
 				break;
 
 			case LOG_FMT_CLIENTIP:  // %Ci
-				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->prod->addr.from,
+				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->prod->conn.addr.from,
 					    dst + maxsize - tmplog, tmp);
 				if (ret == NULL)
 					goto out;
@@ -845,10 +845,10 @@
 				break;
 
 			case LOG_FMT_CLIENTPORT:  // %Cp
-				if (s->req->prod->addr.from.ss_family == AF_UNIX) {
+				if (s->req->prod->conn.addr.from.ss_family == AF_UNIX) {
 					ret = ltoa_o(s->listener->luid, tmplog, dst + maxsize - tmplog);
 				} else {
-					ret = lf_port(tmplog, (struct sockaddr *)&s->req->prod->addr.from,
+					ret = lf_port(tmplog, (struct sockaddr *)&s->req->prod->conn.addr.from,
 						      dst + maxsize - tmplog, tmp);
 				}
 				if (ret == NULL)
@@ -858,8 +858,8 @@
 				break;
 
 			case LOG_FMT_FRONTENDIP: // %Fi
-				si_get_to_addr(s->req->prod);
-				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->prod->addr.to,
+				conn_get_to_addr(&s->req->prod->conn);
+				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->prod->conn.addr.to,
 					    dst + maxsize - tmplog, tmp);
 				if (ret == NULL)
 					goto out;
@@ -868,12 +868,12 @@
 				break;
 
 			case  LOG_FMT_FRONTENDPORT: // %Fp
-				si_get_to_addr(s->req->prod);
-				if (s->req->prod->addr.to.ss_family == AF_UNIX) {
+				conn_get_to_addr(&s->req->prod->conn);
+				if (s->req->prod->conn.addr.to.ss_family == AF_UNIX) {
 					ret = ltoa_o(s->listener->luid,
 						     tmplog, dst + maxsize - tmplog);
 				} else {
-					ret = lf_port(tmplog, (struct sockaddr *)&s->req->prod->addr.to,
+					ret = lf_port(tmplog, (struct sockaddr *)&s->req->prod->conn.addr.to,
 						      dst + maxsize - tmplog, tmp);
 				}
 				if (ret == NULL)
@@ -883,7 +883,7 @@
 				break;
 
 			case LOG_FMT_BACKENDIP:  // %Bi
-				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->cons->addr.from,
+				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->cons->conn.addr.from,
 					    dst + maxsize - tmplog, tmp);
 				if (ret == NULL)
 					goto out;
@@ -892,7 +892,7 @@
 				break;
 
 			case LOG_FMT_BACKENDPORT:  // %Bp
-				ret = lf_port(tmplog, (struct sockaddr *)&s->req->cons->addr.from,
+				ret = lf_port(tmplog, (struct sockaddr *)&s->req->cons->conn.addr.from,
 					      dst + maxsize - tmplog, tmp);
 				if (ret == NULL)
 					goto out;
@@ -901,7 +901,7 @@
 				break;
 
 			case LOG_FMT_SERVERIP: // %Si
-				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->cons->addr.to,
+				ret = lf_ip(tmplog, (struct sockaddr *)&s->req->cons->conn.addr.to,
 					    dst + maxsize - tmplog, tmp);
 				if (ret == NULL)
 					goto out;
@@ -910,7 +910,7 @@
 				break;
 
 			case LOG_FMT_SERVERPORT: // %Sp
-				ret = lf_port(tmplog, (struct sockaddr *)&s->req->cons->addr.to,
+				ret = lf_port(tmplog, (struct sockaddr *)&s->req->cons->conn.addr.to,
 					      dst + maxsize - tmplog, tmp);
 				if (ret == NULL)
 					goto out;
diff --git a/src/peers.c b/src/peers.c
index eb9b13b..6af5d9c 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -1136,7 +1136,7 @@
 	t->context = s;
 	t->nice = l->nice;
 
-	memcpy(&s->si[1].addr.to, &peer->addr, sizeof(s->si[1].addr.to));
+	memcpy(&s->si[1].conn.addr.to, &peer->addr, sizeof(s->si[1].conn.addr.to));
 	s->task = t;
 	s->listener = l;
 
@@ -1148,8 +1148,6 @@
 
 	s->req = s->rep = NULL; /* will be allocated later */
 
-	s->si[0].conn.peeraddr = NULL;
-	s->si[0].conn.peerlen  = 0;
 	s->si[0].conn.t.sock.fd = -1;
 	s->si[0].conn.flags = CO_FL_NONE;
 	s->si[0].owner = t;
@@ -1168,8 +1166,6 @@
 	s->si[0].applet.st0 = PEER_SESSION_CONNECT;
 	s->si[0].conn.data_ctx = (void *)ps;
 
-	s->si[1].conn.peeraddr = NULL;
-	s->si[1].conn.peerlen  = 0;
 	s->si[1].conn.t.sock.fd = -1; /* just to help with debugging */
 	s->si[1].conn.flags = CO_FL_NONE;
 	s->si[1].owner = t;
diff --git a/src/proto_http.c b/src/proto_http.c
index 0344d96..a5df1fd 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -3269,7 +3269,7 @@
 	 * parsing incoming request.
 	 */
 	if ((s->be->options & PR_O_HTTP_PROXY) && !(s->flags & SN_ADDR_SET)) {
-		url2sa(req->buf.p + msg->sl.rq.u, msg->sl.rq.u_l, &s->req->cons->addr.to);
+		url2sa(req->buf.p + msg->sl.rq.u, msg->sl.rq.u_l, &s->req->cons->conn.addr.to);
 	}
 
 	/*
@@ -3319,19 +3319,19 @@
 			 * and we found it, so don't do anything.
 			 */
 		}
-		else if (s->req->prod->addr.from.ss_family == AF_INET) {
+		else if (s->req->prod->conn.addr.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->req->prod->addr.from)->sin_addr.s_addr & s->fe->except_mask.s_addr)
+			     (((struct sockaddr_in *)&s->req->prod->conn.addr.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->req->prod->addr.from)->sin_addr.s_addr & s->be->except_mask.s_addr)
+			     (((struct sockaddr_in *)&s->req->prod->conn.addr.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->req->prod->addr.from)->sin_addr;
+				pn = (unsigned char *)&((struct sockaddr_in *)&s->req->prod->conn.addr.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.
@@ -3351,14 +3351,14 @@
 					goto return_bad_req;
 			}
 		}
-		else if (s->req->prod->addr.from.ss_family == AF_INET6) {
+		else if (s->req->prod->conn.addr.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->req->prod->addr.from))->sin6_addr,
+				  (const void *)&((struct sockaddr_in6 *)(&s->req->prod->conn.addr.from))->sin6_addr,
 				  pn, sizeof(pn));
 
 			/* Note: we rely on the backend to get the header name to be used for
@@ -3387,22 +3387,22 @@
 	if ((s->fe->options | s->be->options) & PR_O_ORGTO) {
 
 		/* FIXME: don't know if IPv6 can handle that case too. */
-		if (s->req->prod->addr.from.ss_family == AF_INET) {
+		if (s->req->prod->conn.addr.from.ss_family == AF_INET) {
 			/* Add an X-Original-To header unless the destination IP is
 			 * in the 'except' network range.
 			 */
-			si_get_to_addr(s->req->prod);
+			conn_get_to_addr(&s->req->prod->conn);
 
-			if (s->req->prod->addr.to.ss_family == AF_INET &&
+			if (s->req->prod->conn.addr.to.ss_family == AF_INET &&
 			    ((!s->fe->except_mask_to.s_addr ||
-			      (((struct sockaddr_in *)&s->req->prod->addr.to)->sin_addr.s_addr & s->fe->except_mask_to.s_addr)
+			      (((struct sockaddr_in *)&s->req->prod->conn.addr.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->req->prod->addr.to)->sin_addr.s_addr & s->be->except_mask_to.s_addr)
+			      (((struct sockaddr_in *)&s->req->prod->conn.addr.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->req->prod->addr.to)->sin_addr;
+				pn = (unsigned char *)&((struct sockaddr_in *)&s->req->prod->conn.addr.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.
@@ -7279,7 +7279,7 @@
 	es->sid  = s->uniq_id;
 	es->srv  = target_srv(&s->target);
 	es->oe   = other_end;
-	es->src  = s->req->prod->addr.from;
+	es->src  = s->req->prod->conn.addr.from;
 	es->state = state;
 	es->ev_id = error_snapshot_id++;
 	es->b_flags = buf->flags;
@@ -7858,11 +7858,11 @@
 	CHECK_HTTP_MESSAGE_FIRST();
 
 	/* Parse HTTP request */
-	url2sa(txn->req.buf->buf.p + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->req->cons->addr.to);
-	if (((struct sockaddr_in *)&l4->req->cons->addr.to)->sin_family != AF_INET)
+	url2sa(txn->req.buf->buf.p + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->req->cons->conn.addr.to);
+	if (((struct sockaddr_in *)&l4->req->cons->conn.addr.to)->sin_family != AF_INET)
 		return 0;
 	smp->type = SMP_T_IPV4;
-	smp->data.ipv4 = ((struct sockaddr_in *)&l4->req->cons->addr.to)->sin_addr;
+	smp->data.ipv4 = ((struct sockaddr_in *)&l4->req->cons->conn.addr.to)->sin_addr;
 
 	/*
 	 * If we are parsing url in frontend space, we prepare backend stage
@@ -7884,9 +7884,9 @@
 	CHECK_HTTP_MESSAGE_FIRST();
 
 	/* Same optimization as url_ip */
-	url2sa(txn->req.buf->buf.p + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->req->cons->addr.to);
+	url2sa(txn->req.buf->buf.p + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->req->cons->conn.addr.to);
 	smp->type = SMP_T_UINT;
-	smp->data.uint = ntohs(((struct sockaddr_in *)&l4->req->cons->addr.to)->sin_port);
+	smp->data.uint = ntohs(((struct sockaddr_in *)&l4->req->cons->conn.addr.to)->sin_port);
 
 	if (px->options & PR_O_HTTP_PROXY)
 		l4->flags |= SN_ADDR_SET;
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index de7f4c5..b793df3 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -232,21 +232,22 @@
 	int fd;
 	struct server *srv;
 	struct proxy *be;
+	struct connection *conn = &si->conn;
 
-	switch (si->conn.target.type) {
+	switch (conn->target.type) {
 	case TARG_TYPE_PROXY:
-		be = si->conn.target.ptr.p;
+		be = conn->target.ptr.p;
 		srv = NULL;
 		break;
 	case TARG_TYPE_SERVER:
-		srv = si->conn.target.ptr.s;
+		srv = conn->target.ptr.s;
 		be = srv->proxy;
 		break;
 	default:
 		return SN_ERR_INTERNAL;
 	}
 
-	if ((fd = si->conn.t.sock.fd = socket(si->addr.to.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+	if ((fd = conn->t.sock.fd = socket(conn->addr.to.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
 		qfprintf(stderr, "Cannot get a server socket.\n");
 
 		if (errno == ENFILE)
@@ -336,11 +337,11 @@
 				fdinfo[fd].port_range = srv->sport_range;
 				set_host_port(&src, fdinfo[fd].local_port);
 
-				ret = tcp_bind_socket(fd, flags, &src, &si->addr.from);
+				ret = tcp_bind_socket(fd, flags, &src, &conn->addr.from);
 			} while (ret != 0); /* binding NOK */
 		}
 		else {
-			ret = tcp_bind_socket(fd, flags, &srv->source_addr, &si->addr.from);
+			ret = tcp_bind_socket(fd, flags, &srv->source_addr, &conn->addr.from);
 		}
 
 		if (ret) {
@@ -383,7 +384,7 @@
 		if (be->iface_name)
 			setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, be->iface_name, be->iface_len + 1);
 #endif
-		ret = tcp_bind_socket(fd, flags, &be->source_addr, &si->addr.from);
+		ret = tcp_bind_socket(fd, flags, &be->source_addr, &conn->addr.from);
 		if (ret) {
 			close(fd);
 			if (ret == 1) {
@@ -418,12 +419,7 @@
 	if (global.tune.server_rcvbuf)
                 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &global.tune.server_rcvbuf, sizeof(global.tune.server_rcvbuf));
 
-	si->flags &= ~SI_FL_FROM_SET;
-
-	si->conn.peeraddr = (struct sockaddr *)&si->addr.to;
-	si->conn.peerlen  = get_addr_len(&si->addr.to);
-
-	if ((connect(fd, si->conn.peeraddr, si->conn.peerlen) == -1) &&
+	if ((connect(fd, (struct sockaddr *)&conn->addr.to, get_addr_len(&conn->addr.to)) == -1) &&
 	    (errno != EINPROGRESS) && (errno != EALREADY) && (errno != EISCONN)) {
 
 		if (errno == EAGAIN || errno == EADDRINUSE) {
@@ -459,25 +455,25 @@
 
 	/* needs src ip/port for logging */
 	if (si->flags & SI_FL_SRC_ADDR)
-		si_get_from_addr(si);
+		conn_get_from_addr(conn);
 
-	fdtab[fd].owner = &si->conn;
+	fdtab[fd].owner = conn;
 	fdtab[fd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY;
-	si->conn.flags  = CO_FL_WAIT_L4_CONN; /* connection in progress */
-	si->conn.flags |= CO_FL_NOTIFY_SI; /* we're on a stream_interface */
+	conn->flags  = CO_FL_WAIT_L4_CONN; /* connection in progress */
+	conn->flags |= CO_FL_NOTIFY_SI; /* we're on a stream_interface */
 
 	/* Prepare to send a few handshakes related to the on-wire protocol. */
 	if (si->send_proxy_ofs)
-		si->conn.flags |= CO_FL_SI_SEND_PROXY;
+		conn->flags |= CO_FL_SI_SEND_PROXY;
 
 	fdtab[fd].iocb = conn_fd_handler;
 	fd_insert(fd);
-	conn_sock_want_send(&si->conn);  /* for connect status */
+	conn_sock_want_send(conn);  /* for connect status */
 	if (!channel_is_empty(si->ob))
-		conn_data_want_send(&si->conn);  /* prepare to send data if any */
+		conn_data_want_send(conn);  /* prepare to send data if any */
 
 	si->state = SI_ST_CON;
-	if (si->conn.data->rcv_pipe && si->conn.data->snd_pipe)
+	if (conn->data->rcv_pipe && conn->data->snd_pipe)
 		si->flags |= SI_FL_CAP_SPLTCP; /* TCP supports splicing */
 	si->exp = tick_add_ifset(now_ms, be->timeout.connect);
 
@@ -549,7 +545,7 @@
 	 *  - connecting (EALREADY, EINPROGRESS)
 	 *  - connected (EISCONN, 0)
 	 */
-	if ((connect(fd, conn->peeraddr, conn->peerlen) < 0)) {
+	if (connect(fd, (struct sockaddr *)&conn->addr.to, get_addr_len(&conn->addr.to)) < 0) {
 		if (errno == EALREADY || errno == EINPROGRESS) {
 			conn_sock_stop_recv(conn);
 			conn_sock_poll_send(conn);
@@ -1505,13 +1501,13 @@
 smp_fetch_src(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
               const struct arg *args, struct sample *smp)
 {
-	switch (l4->si[0].addr.from.ss_family) {
+	switch (l4->si[0].conn.addr.from.ss_family) {
 	case AF_INET:
-		smp->data.ipv4 = ((struct sockaddr_in *)&l4->si[0].addr.from)->sin_addr;
+		smp->data.ipv4 = ((struct sockaddr_in *)&l4->si[0].conn.addr.from)->sin_addr;
 		smp->type = SMP_T_IPV4;
 		break;
 	case AF_INET6:
-		smp->data.ipv6 = ((struct sockaddr_in6 *)(&l4->si[0].addr.from))->sin6_addr;
+		smp->data.ipv6 = ((struct sockaddr_in6 *)(&l4->si[0].conn.addr.from))->sin6_addr;
 		smp->type = SMP_T_IPV6;
 		break;
 	default:
@@ -1528,7 +1524,7 @@
                 const struct arg *args, struct sample *smp)
 {
 	smp->type = SMP_T_UINT;
-	if (!(smp->data.uint = get_host_port(&l4->si[0].addr.from)))
+	if (!(smp->data.uint = get_host_port(&l4->si[0].conn.addr.from)))
 		return 0;
 
 	smp->flags = 0;
@@ -1540,15 +1536,15 @@
 smp_fetch_dst(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
               const struct arg *args, struct sample *smp)
 {
-	si_get_to_addr(&l4->si[0]);
+	conn_get_to_addr(&l4->si[0].conn);
 
-	switch (l4->si[0].addr.to.ss_family) {
+	switch (l4->si[0].conn.addr.to.ss_family) {
 	case AF_INET:
-		smp->data.ipv4 = ((struct sockaddr_in *)&l4->si[0].addr.to)->sin_addr;
+		smp->data.ipv4 = ((struct sockaddr_in *)&l4->si[0].conn.addr.to)->sin_addr;
 		smp->type = SMP_T_IPV4;
 		break;
 	case AF_INET6:
-		smp->data.ipv6 = ((struct sockaddr_in6 *)(&l4->si[0].addr.to))->sin6_addr;
+		smp->data.ipv6 = ((struct sockaddr_in6 *)(&l4->si[0].conn.addr.to))->sin6_addr;
 		smp->type = SMP_T_IPV6;
 		break;
 	default:
@@ -1564,10 +1560,10 @@
 smp_fetch_dport(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                 const struct arg *args, struct sample *smp)
 {
-	si_get_to_addr(&l4->si[0]);
+	conn_get_to_addr(&l4->si[0].conn);
 
 	smp->type = SMP_T_UINT;
-	if (!(smp->data.uint = get_host_port(&l4->si[0].addr.to)))
+	if (!(smp->data.uint = get_host_port(&l4->si[0].conn.addr.to)))
 		return 0;
 
 	smp->flags = 0;
diff --git a/src/session.c b/src/session.c
index b5c7645..0782419 100644
--- a/src/session.c
+++ b/src/session.c
@@ -87,9 +87,7 @@
 	s->si[0].conn.t.sock.fd = cfd;
 	s->si[0].conn.ctrl = l->proto;
 	s->si[0].conn.flags = CO_FL_NONE | CO_FL_NOTIFY_SI; /* we're on a stream_interface */
-	s->si[0].addr.from = *addr;
-	s->si[0].conn.peeraddr = (struct sockaddr *)&s->si[0].addr.from;
-	s->si[0].conn.peerlen  = sizeof(s->si[0].addr.from);
+	s->si[0].conn.addr.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;
diff --git a/src/stream_interface.c b/src/stream_interface.c
index 5776519..cb33476 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -504,7 +504,7 @@
 		 * (which is recomputed every time since it's constant). If
 		 * it is positive, it means we have to send from the start.
 		 */
-		ret = make_proxy_line(trash, trashlen, &si->ob->prod->addr.from, &si->ob->prod->addr.to);
+		ret = make_proxy_line(trash, trashlen, &si->ob->prod->conn.addr.from, &si->ob->prod->conn.addr.to);
 		if (!ret)
 			goto out_error;