Merge branch 'rfc2616' into switch
diff --git a/Makefile b/Makefile
index 50be7d0..1eef960 100644
--- a/Makefile
+++ b/Makefile
@@ -92,14 +92,60 @@
 # set some defines when needed.
 # Known ones are -DENABLE_POLL, -DENABLE_EPOLL, and -DUSE_MY_EPOLL
 # - use -DTPROXY to compile with transparent proxy support.
+# - use -DCONFIG_HAP_CTTPROXY to enable full transparent proxy support
 DEFINE = -DTPROXY
 
+
+#### build options
+
+# do not change this one, enable USE_* variables instead.
+OPTIONS =
+
+ifneq ($(USE_CTTPROXY),)
+OPTIONS += -DCONFIG_HAP_CTTPROXY
+endif
+
+ifneq ($(USE_TPROXY),)
+OPTIONS += -DTPROXY
+endif
+
+ifneq ($(USE_POLL),)
+OPTIONS += -DENABLE_POLL
+endif
+
+ifneq ($(USE_EPOLL),)
+OPTIONS += -DENABLE_EPOLL
+endif
+
+ifneq ($(USE_MY_EPOLL),)
+OPTIONS += -DUSE_MY_EPOLL
+endif
+
+ifneq ($(USE_NETFILTER),)
+OPTIONS += -DNETFILTER
+endif
+
+ifneq ($(USE_EPOLL_WORKAROUND),)
+OPTIONS += -DEPOLL_CTL_MOD_WORKAROUND
+endif
+
+ifneq ($(USE_GETSOCKNAME),)
+OPTIONS += -DUSE_GETSOCKNAME
+endif
+
+ifneq ($(USE_REGPARM),)
+OPTIONS += -DCONFIG_HAP_USE_REGPARM
+endif
+
+#### end of build options
+
+
 # global options
 TARGET_OPTS=$(COPTS.$(TARGET))
 REGEX_OPTS=$(COPTS.$(REGEX))
 CPU_OPTS=$(COPTS.$(CPU))
 
-COPTS=-Iinclude $(ADDINC) $(CPU_OPTS) $(TARGET_OPTS) $(REGEX_OPTS) $(SMALL_OPTS) $(DEFINE)
+COPTS=-Iinclude $(ADDINC) $(CPU_OPTS) $(TARGET_OPTS) $(REGEX_OPTS) $(SMALL_OPTS) $(DEFINE) $(OPTIONS)
 LIBS=$(LIBS.$(TARGET)) $(LIBS.$(REGEX)) $(ADDLIB)
 
 CFLAGS = -Wall $(COPTS) $(DEBUG)
diff --git a/include/common/compat.h b/include/common/compat.h
index 58908d7..8261f8f 100644
--- a/include/common/compat.h
+++ b/include/common/compat.h
@@ -49,6 +49,19 @@
 #include <linux/netfilter_ipv4.h>
 #endif
 
+/* We'll try to enable SO_REUSEPORT on Linux 2.4 and 2.6 if not defined.
+ * There are two families of values depending on the architecture. Those
+ * are at least valid on Linux 2.4 and 2.6, reason why we'll rely on the
+ * NETFILTER define.
+ */
+#if !defined(SO_REUSEPORT) && defined(NETFILTER)
+#if    (SO_REUSEADDR == 2)
+#define SO_REUSEPORT 15
+#elif  (SO_REUSEADDR == 0x0004)
+#define SO_REUSEPORT 0x0200
+#endif /* SO_REUSEADDR */
+#endif /* SO_REUSEPORT */
+
 #if defined(__dietlibc__)
 #include <strings.h>
 #endif
diff --git a/include/import/ip_tproxy.h b/include/import/ip_tproxy.h
new file mode 100644
index 0000000..d33f14d
--- /dev/null
+++ b/include/import/ip_tproxy.h
@@ -0,0 +1,77 @@
+/*
+ * Transparent proxy support for Linux/iptables
+ *
+ * Copyright (c) 2002-2004 BalaBit IT Ltd.
+ * Author: Balázs Scheidler
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _IP_TPROXY_H
+#define _IP_TPROXY_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/in.h>
+#else
+#include <netinet/in.h>
+#ifndef IP_RECVORIGADDRS
+#define IP_RECVORIGADDRS	11273
+#define IP_ORIGADDRS	IP_RECVORIGADDRS
+struct in_origaddrs {
+        struct in_addr ioa_srcaddr;
+        struct in_addr ioa_dstaddr;
+        unsigned short int ioa_srcport;
+        unsigned short int ioa_dstport;
+};
+#endif
+#endif
+
+/* 
+ * used in setsockopt(SOL_IP, IP_TPROXY) should not collide 
+ * with values in <linux/in.h> 
+ */
+
+#define IP_TPROXY	   11274
+
+/* tproxy operations */
+enum {
+	TPROXY_VERSION = 0,
+	TPROXY_ASSIGN,
+	TPROXY_UNASSIGN,
+	TPROXY_QUERY,
+	TPROXY_FLAGS,
+	TPROXY_ALLOC,
+	TPROXY_CONNECT
+};
+
+/* bitfields in IP_TPROXY_FLAGS */
+#define ITP_CONNECT     0x00000001
+#define ITP_LISTEN      0x00000002
+#define ITP_ESTABLISHED 0x00000004
+
+#define ITP_ONCE        0x00010000
+#define ITP_MARK        0x00020000
+#define ITP_APPLIED     0x00040000
+#define ITP_UNIDIR      0x00080000
+
+struct in_tproxy_addr{
+	struct in_addr	faddr;
+	u_int16_t	fport;
+};
+
+struct in_tproxy {
+	/* fixed part, should not change between versions */
+	u_int32_t op;
+	/* extensible part */
+	union _in_args {
+		u_int32_t		version;
+		struct in_tproxy_addr	addr;
+		u_int32_t		flags;
+	} v;
+};
+
+#endif
diff --git a/include/types/backend.h b/include/types/backend.h
index a6a393a..f70a370 100644
--- a/include/types/backend.h
+++ b/include/types/backend.h
@@ -53,6 +53,12 @@
 #define PR_O_ABRT_CLOSE 0x00800000      /* immediately abort request when client closes */
 #define PR_O_SSL3_CHK   0x01000000      /* use SSLv3 CLIENT_HELLO packets for server health */
 
+#define	PR_O_TPXY_ADDR  0x02000000	/* bind to this non-local address when connect()ing */
+#define	PR_O_TPXY_CIP	0x04000000	/* bind to the client's IP address when connect()ing */
+#define	PR_O_TPXY_CLI	0x06000000	/* bind to the client's IP+port when connect()ing */
+#define	PR_O_TPXY_MASK	0x06000000	/* bind to a non-local address when connect()ing */
+
+
 #endif /* _TYPES_BACKEND_H */
 
 /*
diff --git a/include/types/global.h b/include/types/global.h
index 681ac05..40c6c99 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -38,22 +38,27 @@
 #define	MODE_STARTING	128
 #define	MODE_FOREGROUND	256
 
+/* list of last checks to perform, depending on config options */
+#define LSTCHK_CAP_BIND	0x00000001	/* check that we can bind to any port */
+#define LSTCHK_CTTPROXY	0x00000002	/* check that tproxy is enabled */
+#define LSTCHK_NETADM	0x00000004	/* check that we have CAP_NET_ADMIN */
 
 /* FIXME : this will have to be redefined correctly */
 struct global {
-    int uid;
-    int gid;
-    int nbproc;
-    int maxconn;
-    int maxsock;		/* max # of sockets */
-    int rlimit_nofile;		/* default ulimit-n value : 0=unset */
-    int rlimit_memmax;		/* default ulimit-d in megs value : 0=unset */
-    int mode;
-    char *chroot;
-    char *pidfile;
-    int logfac1, logfac2;
-    int loglev1, loglev2;
-    struct sockaddr_in logsrv1, logsrv2;
+	int uid;
+	int gid;
+	int nbproc;
+	int maxconn;
+	int maxsock;		/* max # of sockets */
+	int rlimit_nofile;	/* default ulimit-n value : 0=unset */
+	int rlimit_memmax;	/* default ulimit-d in megs value : 0=unset */
+	int mode;
+	int last_checks;
+	char *chroot;
+	char *pidfile;
+	int logfac1, logfac2;
+	int loglev1, loglev2;
+	struct sockaddr_in logsrv1, logsrv2;
 };
 
 extern struct global global;
diff --git a/include/types/proxy.h b/include/types/proxy.h
index f3304e6..8523a69 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -102,6 +102,9 @@
 	int options;				/* PR_O_REDISP, PR_O_TRANSP, ... */
 	int mode;				/* mode = PR_MODE_TCP, PR_MODE_HTTP or PR_MODE_HEALTH */
 	struct sockaddr_in source_addr;		/* the address to which we want to bind for connect() */
+#ifdef CONFIG_HAP_CTTPROXY
+	struct sockaddr_in tproxy_addr;		/* non-local address we want to bind to for connect() */
+#endif
 	struct proxy *next;
 	struct sockaddr_in logsrv1, logsrv2;	/* 2 syslog servers */
 	signed char logfac1, logfac2;		/* log facility for both servers. -1 = disabled */
diff --git a/include/types/server.h b/include/types/server.h
index 37b8af1..70e1f8f 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -35,11 +35,16 @@
 
 
 /* server flags */
-#define SRV_RUNNING	1	/* the server is UP */
-#define SRV_BACKUP	2	/* this server is a backup server */
-#define	SRV_MAPPORTS	4	/* this server uses mapped ports */
-#define	SRV_BIND_SRC	8	/* this server uses a specific source address */
-#define	SRV_CHECKED	16	/* this server needs to be checked */
+#define SRV_RUNNING	0x0001	/* the server is UP */
+#define SRV_BACKUP	0x0002	/* this server is a backup server */
+#define SRV_MAPPORTS	0x0004	/* this server uses mapped ports */
+#define SRV_BIND_SRC	0x0008	/* this server uses a specific source address */
+#define SRV_CHECKED	0x0010	/* this server needs to be checked */
+
+#define SRV_TPROXY_ADDR	0x0020	/* bind to this non-local address to reach this server */
+#define SRV_TPROXY_CIP	0x0040	/* bind to the client's IP address to reach this server */
+#define SRV_TPROXY_CLI	0x0060	/* bind to the client's IP+port to reach this server */
+#define SRV_TPROXY_MASK	0x0060	/* bind to a non-local address to reach this server */
 
 /* function which act on servers need to return various errors */
 #define SRV_STATUS_OK       0   /* everything is OK. */
@@ -60,6 +65,9 @@
 	struct task *queue_mgt;		/* the task associated to the queue processing */
 	struct sockaddr_in addr;		/* the address to connect to */
 	struct sockaddr_in source_addr;	/* the address to which we want to bind for connect() */
+#ifdef CONFIG_HAP_CTTPROXY
+	struct sockaddr_in tproxy_addr;	/* non-local address we want to bind to for connect() */
+#endif
 	short check_port;			/* the port to use for the health checks */
 	int health;				/* 0->rise-1 = bad; rise->rise+fall-1 = good */
 	int rise, fall;			/* time in iterations */
diff --git a/include/types/session.h b/include/types/session.h
index 66b1db3..dd12d4f 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -103,7 +103,9 @@
 struct session {
 	struct task *task;			/* the task associated with this session */
 	/* application specific below */
-	struct proxy *proxy;			/* the proxy this socket belongs to */
+	struct proxy *fe;			/* the proxy this session depends on for the client side */
+	struct proxy *fi;			/* the proxy this session depends on for the filtering rules */
+	struct proxy *be;			/* the proxy this session depends on for the server side */
 	int cli_fd;				/* the client side fd */
 	int srv_fd;				/* the server side fd */
 	int cli_state;				/* state of the client side */
@@ -144,7 +146,7 @@
 			struct server *sv;
 			short px_st, sv_st;	/* DATA_ST_INIT or DATA_ST_DATA */
 		} stats;
-	} data_ctx;
+	} data_ctx;				/* used by produce_content to dump the stats right now */
 	unsigned int uniq_id;			/* unique ID used for the traces */
 };
 
diff --git a/src/backend.c b/src/backend.c
index 2884ea5..e01068f 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -15,6 +15,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <syslog.h>
+#include <string.h>
 
 #include <common/compat.h>
 #include <common/config.h>
@@ -35,6 +36,9 @@
 #include <proto/stream_sock.h>
 #include <proto/task.h>
 
+#ifdef CONFIG_HAP_CTTPROXY
+#include <import/ip_tproxy.h>
+#endif
 
 /*
  * This function recounts the number of usable active and backup servers for
@@ -151,16 +155,16 @@
 		return SRV_STATUS_INTERNAL;
 
 	if (!(s->flags & SN_ASSIGNED)) {
-		if ((s->proxy->options & PR_O_BALANCE) && !(s->flags & SN_DIRECT)) {
-			if (!s->proxy->srv_act && !s->proxy->srv_bck)
+		if ((s->be->options & PR_O_BALANCE) && !(s->flags & SN_DIRECT)) {
+			if (!s->be->srv_act && !s->be->srv_bck)
 				return SRV_STATUS_NOSRV;
 
-			if (s->proxy->options & PR_O_BALANCE_RR) {
-				s->srv = get_server_rr_with_conns(s->proxy);
+			if (s->be->options & PR_O_BALANCE_RR) {
+				s->srv = get_server_rr_with_conns(s->be);
 				if (!s->srv)
 					return SRV_STATUS_FULL;
 			}
-			else if (s->proxy->options & PR_O_BALANCE_SH) {
+			else if (s->be->options & PR_O_BALANCE_SH) {
 				int len;
 		
 				if (s->cli_addr.ss_family == AF_INET)
@@ -170,7 +174,7 @@
 				else /* unknown IP family */
 					return SRV_STATUS_INTERNAL;
 		
-				s->srv = get_server_sh(s->proxy,
+				s->srv = get_server_sh(s->be,
 						       (void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
 						       len);
 			}
@@ -202,7 +206,7 @@
 	fprintf(stderr,"assign_server_address : s=%p\n",s);
 #endif
 
-	if (s->flags & SN_DIRECT || s->proxy->options & PR_O_BALANCE) {
+	if (s->flags & SN_DIRECT || s->be->options & PR_O_BALANCE) {
 		/* A server is necessarily known for this session */
 		if (!(s->flags & SN_ASSIGNED))
 			return SRV_STATUS_INTERNAL;
@@ -215,17 +219,17 @@
 			struct sockaddr_in sockname;
 			socklen_t namelen = sizeof(sockname);
 
-			if (!(s->proxy->options & PR_O_TRANSP) ||
+			if (!(s->fe->options & PR_O_TRANSP) ||
 			    get_original_dst(s->cli_fd, (struct sockaddr_in *)&sockname, &namelen) == -1)
 				getsockname(s->cli_fd, (struct sockaddr *)&sockname, &namelen);
 			s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) + ntohs(sockname.sin_port));
 		}
 	}
-	else if (*(int *)&s->proxy->dispatch_addr.sin_addr) {
+	else if (*(int *)&s->be->dispatch_addr.sin_addr) {
 		/* connect to the defined dispatch addr */
-		s->srv_addr = s->proxy->dispatch_addr;
+		s->srv_addr = s->be->dispatch_addr;
 	}
-	else if (s->proxy->options & PR_O_TRANSP) {
+	else if (s->fe->options & PR_O_TRANSP) {
 		/* in transparent mode, use the original dest addr if no dispatch specified */
 		socklen_t salen = sizeof(s->srv_addr);
 
@@ -335,17 +339,17 @@
 		qfprintf(stderr, "Cannot get a server socket.\n");
 
 		if (errno == ENFILE)
-			send_log(s->proxy, LOG_EMERG,
+			send_log(s->be, LOG_EMERG,
 				 "Proxy %s reached system FD limit at %d. Please check system tunables.\n",
-				 s->proxy->id, maxfd);
+				 s->be->id, maxfd);
 		else if (errno == EMFILE)
-			send_log(s->proxy, LOG_EMERG,
+			send_log(s->be, LOG_EMERG,
 				 "Proxy %s reached process FD limit at %d. Please check 'ulimit-n' and restart.\n",
-				 s->proxy->id, maxfd);
+				 s->be->id, maxfd);
 		else if (errno == ENOBUFS || errno == ENOMEM)
-			send_log(s->proxy, LOG_EMERG,
+			send_log(s->be, LOG_EMERG,
 				 "Proxy %s reached system memory limit at %d sockets. Please check system tunables.\n",
-				 s->proxy->id, maxfd);
+				 s->be->id, maxfd);
 		/* this is a resource error */
 		return SN_ERR_RESOURCE;
 	}
@@ -366,7 +370,7 @@
 		return SN_ERR_INTERNAL;
 	}
 
-	if (s->proxy->options & PR_O_TCP_SRV_KA)
+	if (s->be->options & PR_O_TCP_SRV_KA)
 		setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one));
 
 	/* allow specific binding :
@@ -377,24 +381,96 @@
 		setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one));
 		if (bind(fd, (struct sockaddr *)&s->srv->source_addr, sizeof(s->srv->source_addr)) == -1) {
 			Alert("Cannot bind to source address before connect() for server %s/%s. Aborting.\n",
-			      s->proxy->id, s->srv->id);
+			      s->be->id, s->srv->id);
 			close(fd);
-			send_log(s->proxy, LOG_EMERG,
+			send_log(s->be, LOG_EMERG,
 				 "Cannot bind to source address before connect() for server %s/%s.\n",
-				 s->proxy->id, s->srv->id);
+				 s->be->id, s->srv->id);
 			return SN_ERR_RESOURCE;
 		}
+#ifdef CONFIG_HAP_CTTPROXY
+		if (s->srv->state & SRV_TPROXY_MASK) {
+			struct in_tproxy itp1, itp2;
+			memset(&itp1, 0, sizeof(itp1));
+
+			itp1.op = TPROXY_ASSIGN;
+			switch (s->srv->state & SRV_TPROXY_MASK) {
+			case SRV_TPROXY_ADDR:
+				itp1.v.addr.faddr = s->srv->tproxy_addr.sin_addr;
+				itp1.v.addr.fport = s->srv->tproxy_addr.sin_port;
+				break;
+			case SRV_TPROXY_CLI:
+				itp1.v.addr.fport = ((struct sockaddr_in *)&s->cli_addr)->sin_port;
+				/* fall through */
+			case SRV_TPROXY_CIP:
+				/* FIXME: what can we do if the client connects in IPv6 ? */
+				itp1.v.addr.faddr = ((struct sockaddr_in *)&s->cli_addr)->sin_addr;
+				break;
+			}
+
+			/* set connect flag on socket */
+			itp2.op = TPROXY_FLAGS;
+			itp2.v.flags = ITP_CONNECT | ITP_ONCE;
+
+			if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp1, sizeof(itp1)) == -1 ||
+			    setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) == -1) {
+				Alert("Cannot bind to tproxy source address before connect() for server %s/%s. Aborting.\n",
+				      s->be->id, s->srv->id);
+				close(fd);
+				send_log(s->be, LOG_EMERG,
+					 "Cannot bind to tproxy source address before connect() for server %s/%s.\n",
+					 s->be->id, s->srv->id);
+				return SN_ERR_RESOURCE;
+			}
+		}
+#endif
 	}
-	else if (s->proxy->options & PR_O_BIND_SRC) {
+	else if (s->be->options & PR_O_BIND_SRC) {
 		setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one));
-		if (bind(fd, (struct sockaddr *)&s->proxy->source_addr, sizeof(s->proxy->source_addr)) == -1) {
-			Alert("Cannot bind to source address before connect() for proxy %s. Aborting.\n", s->proxy->id);
+		if (bind(fd, (struct sockaddr *)&s->be->source_addr, sizeof(s->be->source_addr)) == -1) {
+			Alert("Cannot bind to source address before connect() for proxy %s. Aborting.\n", s->be->id);
 			close(fd);
-			send_log(s->proxy, LOG_EMERG,
+			send_log(s->be, LOG_EMERG,
 				 "Cannot bind to source address before connect() for server %s/%s.\n",
-				 s->proxy->id, s->srv->id);
+				 s->be->id, s->srv->id);
 			return SN_ERR_RESOURCE;
 		}
+#ifdef CONFIG_HAP_CTTPROXY
+		if (s->be->options & PR_O_TPXY_MASK) {
+			struct in_tproxy itp1, itp2;
+			memset(&itp1, 0, sizeof(itp1));
+
+			itp1.op = TPROXY_ASSIGN;
+			switch (s->be->options & PR_O_TPXY_MASK) {
+			case PR_O_TPXY_ADDR:
+				itp1.v.addr.faddr = s->srv->tproxy_addr.sin_addr;
+				itp1.v.addr.fport = s->srv->tproxy_addr.sin_port;
+				break;
+			case PR_O_TPXY_CLI:
+				itp1.v.addr.fport = ((struct sockaddr_in *)&s->cli_addr)->sin_port;
+				/* fall through */
+			case PR_O_TPXY_CIP:
+				/* FIXME: what can we do if the client connects in IPv6 ? */
+				itp1.v.addr.faddr = ((struct sockaddr_in *)&s->cli_addr)->sin_addr;
+				break;
+			}
+
+			/* set connect flag on socket */
+			itp2.op = TPROXY_FLAGS;
+			itp2.v.flags = ITP_CONNECT | ITP_ONCE;
+
+			if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp1, sizeof(itp1)) == -1 ||
+			    setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) == -1) {
+				Alert("Cannot bind to tproxy source address before connect() for proxy %s. Aborting.\n",
+				      s->be->id);
+				close(fd);
+				send_log(s->be, LOG_EMERG,
+					 "Cannot bind to tproxy source address before connect() for server %s/%s.\n",
+					 s->be->id, s->srv->id);
+				return SN_ERR_RESOURCE;
+			}
+		}
+#endif
 	}
 	
 	if ((connect(fd, (struct sockaddr *)&s->srv_addr, sizeof(s->srv_addr)) == -1) &&
@@ -409,9 +485,9 @@
 
 			qfprintf(stderr,"Cannot connect: %s.\n",msg);
 			close(fd);
-			send_log(s->proxy, LOG_EMERG,
+			send_log(s->be, LOG_EMERG,
 				 "Connect() failed for server %s/%s: %s.\n",
-				 s->proxy->id, s->srv->id, msg);
+				 s->be->id, s->srv->id, msg);
 			return SN_ERR_RESOURCE;
 		} else if (errno == ETIMEDOUT) {
 			//qfprintf(stderr,"Connect(): ETIMEDOUT");
@@ -447,8 +523,8 @@
 			s->srv->cur_sess_max = s->srv->cur_sess;
 	}
 
-	if (s->proxy->contimeout)
-		tv_delayfrom(&s->req->cex, &now, s->proxy->contimeout);
+	if (s->be->contimeout)
+		tv_delayfrom(&s->req->cex, &now, s->be->contimeout);
 	else
 		tv_eternity(&s->req->cex);
 	return SN_ERR_NONE;  /* connection is OK */
@@ -469,15 +545,15 @@
 		/* if not retryable anymore, let's abort */
 		tv_eternity(&t->req->cex);
 		srv_close_with_err(t, conn_err, SN_FINST_C,
-				   503, t->proxy->errmsg.len503, t->proxy->errmsg.msg503);
+				   503, t->fe->errmsg.len503, t->fe->errmsg.msg503);
 		if (t->srv)
 			t->srv->failed_conns++;
-		t->proxy->failed_conns++;
+		t->be->failed_conns++;
 
 		/* We used to have a free connection slot. Since we'll never use it,
 		 * we have to inform the server that it may be used by another session.
 		 */
-		if (may_dequeue_tasks(t->srv, t->proxy))
+		if (may_dequeue_tasks(t->srv, t->be))
 			task_wakeup(&rq, t->srv->queue_mgt);
 		return 1;
 	}
@@ -511,12 +587,12 @@
 		case SN_ERR_INTERNAL:
 			tv_eternity(&t->req->cex);
 			srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
-					   500, t->proxy->errmsg.len500, t->proxy->errmsg.msg500);
+					   500, t->fe->errmsg.len500, t->fe->errmsg.msg500);
 			if (t->srv)
 				t->srv->failed_conns++;
-			t->proxy->failed_conns++;
+			t->be->failed_conns++;
 			/* release other sessions waiting for this server */
-			if (may_dequeue_tasks(t->srv, t->proxy))
+			if (may_dequeue_tasks(t->srv, t->be))
 				task_wakeup(&rq, t->srv->queue_mgt);
 			return 1;
 		}
@@ -524,18 +600,18 @@
 		if (srv_count_retry_down(t, conn_err)) {
 			return 1;
 		}
-	} while (t->srv == NULL || t->conn_retries > 0 || !(t->proxy->options & PR_O_REDISP));
+	} while (t->srv == NULL || t->conn_retries > 0 || !(t->be->options & PR_O_REDISP));
 
 	/* We're on our last chance, and the REDISP option was specified.
 	 * We will ignore cookie and force to balance or use the dispatcher.
 	 */
 	/* let's try to offer this slot to anybody */
-	if (may_dequeue_tasks(t->srv, t->proxy))
+	if (may_dequeue_tasks(t->srv, t->be))
 		task_wakeup(&rq, t->srv->queue_mgt);
 
 	if (t->srv)
 		t->srv->failed_conns++;
-	t->proxy->failed_conns++;
+	t->be->failed_conns++;
 
 	t->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
 	t->srv = NULL; /* it's left to the dispatcher to choose a server */
@@ -571,17 +647,17 @@
 		/* note: it is guaranteed that t->srv == NULL here */
 		tv_eternity(&t->req->cex);
 		srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_C,
-				   503, t->proxy->errmsg.len503, t->proxy->errmsg.msg503);
+				   503, t->fe->errmsg.len503, t->fe->errmsg.msg503);
 		if (t->srv)
 			t->srv->failed_conns++;
-		t->proxy->failed_conns++;
+		t->be->failed_conns++;
 
 		return 1;
 
 	case SRV_STATUS_QUEUED:
 		/* FIXME-20060503 : we should use the queue timeout instead */
-		if (t->proxy->contimeout)
-			tv_delayfrom(&t->req->cex, &now, t->proxy->contimeout);
+		if (t->be->contimeout)
+			tv_delayfrom(&t->req->cex, &now, t->be->contimeout);
 		else
 			tv_eternity(&t->req->cex);
 		t->srv_state = SV_STIDLE;
@@ -593,13 +669,13 @@
 	default:
 		tv_eternity(&t->req->cex);
 		srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
-				   500, t->proxy->errmsg.len500, t->proxy->errmsg.msg500);
+				   500, t->fe->errmsg.len500, t->fe->errmsg.msg500);
 		if (t->srv)
 			t->srv->failed_conns++;
-		t->proxy->failed_conns++;
+		t->be->failed_conns++;
 
 		/* release other sessions waiting for this server */
-		if (may_dequeue_tasks(t->srv, t->proxy))
+		if (may_dequeue_tasks(t->srv, t->be))
 			task_wakeup(&rq, t->srv->queue_mgt);
 		return 1;
 	}
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 034a2f1..9592247 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -1153,6 +1153,30 @@
 				newsrv->state |= SRV_BIND_SRC;
 				newsrv->source_addr = *str2sa(args[cur_arg + 1]);
 				cur_arg += 2;
+#ifdef CONFIG_HAP_CTTPROXY
+				if (!strcmp(args[cur_arg], "usesrc")) {  /* address to use outside */
+					if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
+						Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
+						      file, linenum, "usesrc");
+						return -1;
+					}
+					if (!*args[cur_arg + 1]) {
+						Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
+						      file, linenum, "usesrc");
+						return -1;
+					}
+					if (!strcmp(args[cur_arg + 1], "client")) {
+						newsrv->state |= SRV_TPROXY_CLI;
+					} else if (!strcmp(args[cur_arg + 1], "clientip")) {
+						newsrv->state |= SRV_TPROXY_CIP;
+					} else {
+						newsrv->state |= SRV_TPROXY_ADDR;
+						newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
+					}
+					global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
+					cur_arg += 2;
+				}
+#endif
 			}
 			else {
 				Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'port', 'source', 'minconn', 'maxconn' and 'weight'.\n",
@@ -1241,6 +1265,30 @@
 	
 		curproxy->source_addr = *str2sa(args[1]);
 		curproxy->options |= PR_O_BIND_SRC;
+#ifdef CONFIG_HAP_CTTPROXY
+		if (!strcmp(args[2], "usesrc")) {  /* address to use outside */
+			if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
+				Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
+				      file, linenum, "usesrc");
+				return -1;
+			}
+			if (!*args[3]) {
+				Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
+				      file, linenum, "usesrc");
+				return -1;
+			}
+
+			if (!strcmp(args[3], "client")) {
+				curproxy->options |= PR_O_TPXY_CLI;
+			} else if (!strcmp(args[3], "clientip")) {
+				curproxy->options |= PR_O_TPXY_CIP;
+			} else {
+				curproxy->options |= PR_O_TPXY_ADDR;
+				curproxy->tproxy_addr = *str2sa(args[3]);
+			}
+			global.last_checks |= LSTCHK_CTTPROXY | LSTCHK_NETADM;
+		}
+#endif
 	}
 	else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) {  /* replace request header from a regex */
 		regex_t *preg;
diff --git a/src/checks.c b/src/checks.c
index 9643a2b..8466b75 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -36,6 +36,10 @@
 #include <proto/server.h>
 #include <proto/task.h>
 
+#ifdef CONFIG_HAP_CTTPROXY
+#include <import/ip_tproxy.h>
+#endif
+
 
 /* Sets server <s> down, notifies by all available means, recounts the
  * remaining servers on the proxy and transfers queued sessions whenever
@@ -60,7 +64,7 @@
 		xferred = 0;
 		FOREACH_ITEM_SAFE(pc, pc_bck, &s->pendconns, pc_end, struct pendconn *, list) {
 			sess = pc->sess;
-			if ((sess->proxy->options & PR_O_REDISP)) {
+			if ((sess->be->options & PR_O_REDISP)) {
 				/* The REDISP option was specified. We will ignore
 				 * cookie and force to balance or use the dispatcher.
 				 */
@@ -260,6 +264,27 @@
 						      s->proxy->id, s->id);
 						s->result = -1;
 					}
+#ifdef CONFIG_HAP_CTTPROXY
+					if ((s->state & SRV_TPROXY_MASK) == SRV_TPROXY_ADDR) {
+						struct in_tproxy itp1, itp2;
+						memset(&itp1, 0, sizeof(itp1));
+						
+						itp1.op = TPROXY_ASSIGN;
+						itp1.v.addr.faddr = s->tproxy_addr.sin_addr;
+						itp1.v.addr.fport = s->tproxy_addr.sin_port;
+
+						/* set connect flag on socket */
+						itp2.op = TPROXY_FLAGS;
+						itp2.v.flags = ITP_CONNECT | ITP_ONCE;
+
+						if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp1, sizeof(itp1)) == -1 ||
+						    setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) == -1) {
+							Alert("Cannot bind to tproxy source address before connect() for server %s/%s. Aborting.\n",
+							      s->proxy->id, s->id);
+							s->result = -1;
+						}
+					}
+#endif
 				}
 				else if (s->proxy->options & PR_O_BIND_SRC) {
 					setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one));
@@ -268,6 +293,27 @@
 						      s->proxy->id);
 						s->result = -1;
 					}
+#ifdef CONFIG_HAP_CTTPROXY
+					if ((s->proxy->options & PR_O_TPXY_MASK) == PR_O_TPXY_ADDR) {
+						struct in_tproxy itp1, itp2;
+						memset(&itp1, 0, sizeof(itp1));
+						
+						itp1.op = TPROXY_ASSIGN;
+						itp1.v.addr.faddr = s->tproxy_addr.sin_addr;
+						itp1.v.addr.fport = s->tproxy_addr.sin_port;
+						
+						/* set connect flag on socket */
+						itp2.op = TPROXY_FLAGS;
+						itp2.v.flags = ITP_CONNECT | ITP_ONCE;
+						
+						if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp1, sizeof(itp1)) == -1 ||
+						    setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) == -1) {
+							Alert("Cannot bind to tproxy source address before connect() for proxy %s. Aborting.\n",
+							      s->proxy->id);
+							s->result = -1;
+						}
+					}
+#endif
 				}
 
 				if (!s->result) {
diff --git a/src/client.c b/src/client.c
index e1890f0..26ef186 100644
--- a/src/client.c
+++ b/src/client.c
@@ -156,7 +156,11 @@
 		t->context = s;
 
 		s->task = t;
+#ifdef BUILD_WITH_PROXY
 		s->proxy = p;
+#endif
+		s->be = s->fe = s->fi = p;
+
 		s->cli_state = (p->mode == PR_MODE_HTTP) ?  CL_STHEADERS : CL_STDATA; /* no HTTP headers for non-HTTP proxies */
 		s->srv_state = SV_STIDLE;
 		s->req = s->rep = NULL; /* will be allocated later */
@@ -229,7 +233,7 @@
 			socklen_t namelen = sizeof(sockname);
 
 			if (addr.ss_family != AF_INET ||
-			    !(s->proxy->options & PR_O_TRANSP) ||
+			    !(s->fe->options & PR_O_TRANSP) ||
 			    get_original_dst(cfd, (struct sockaddr_in *)&sockname, &namelen) == -1)
 				getsockname(cfd, (struct sockaddr *)&sockname, &namelen);
 
@@ -270,7 +274,7 @@
 			socklen_t namelen = sizeof(sockname);
 			int len;
 			if (addr.ss_family != AF_INET ||
-			    !(s->proxy->options & PR_O_TRANSP) ||
+			    !(s->fe->options & PR_O_TRANSP) ||
 			    get_original_dst(cfd, (struct sockaddr_in *)&sockname, &namelen) == -1)
 				getsockname(cfd, (struct sockaddr *)&sockname, &namelen);
 
@@ -314,9 +318,9 @@
 		if (s->cli_state == CL_STHEADERS) /* reserve some space for header rewriting */
 			s->req->rlim -= MAXREWRITE;
 
-		s->req->rto = s->proxy->clitimeout;
-		s->req->wto = s->proxy->srvtimeout;
-		s->req->cto = s->proxy->srvtimeout;
+		s->req->rto = s->fe->clitimeout;
+		s->req->wto = s->be->srvtimeout;
+		s->req->cto = s->be->srvtimeout;
 
 		if ((s->rep = pool_alloc(buffer)) == NULL) { /* no memory */
 			pool_free(buffer, s->req);
@@ -332,8 +336,8 @@
 
 		buffer_init(s->rep);
 
-		s->rep->rto = s->proxy->srvtimeout;
-		s->rep->wto = s->proxy->clitimeout;
+		s->rep->rto = s->be->srvtimeout;
+		s->rep->wto = s->be->clitimeout;
 		s->rep->cto = 0;
 
 		fdtab[cfd].owner = t;
@@ -371,11 +375,11 @@
 		tv_eternity(&s->rep->rex);
 		tv_eternity(&s->rep->wex);
 
-		if (s->proxy->clitimeout) {
+		if (s->fe->clitimeout) {
 			if (MY_FD_ISSET(cfd, StaticReadEvent))
-				tv_delayfrom(&s->req->rex, &now, s->proxy->clitimeout);
+				tv_delayfrom(&s->req->rex, &now, s->fe->clitimeout);
 			if (MY_FD_ISSET(cfd, StaticWriteEvent))
-				tv_delayfrom(&s->rep->wex, &now, s->proxy->clitimeout);
+				tv_delayfrom(&s->rep->wex, &now, s->fe->clitimeout);
 		}
 
 		tv_min(&t->expire, &s->req->rex, &s->rep->wex);
diff --git a/src/log.c b/src/log.c
index 3f0625e..fac5d1f 100644
--- a/src/log.c
+++ b/src/log.c
@@ -287,7 +287,11 @@
 void sess_log(struct session *s)
 {
 	char pn[INET6_ADDRSTRLEN + strlen(":65535")];
-	struct proxy *p = s->proxy;
+#if 1  /* FIXME: this should disappear */
+	struct proxy *p = s->fe;
+#endif
+	struct proxy *fe = s->fe;
+	struct proxy *be = s->be;
 	int log;
 	char *uri;
 	char *pxid;
@@ -300,7 +304,7 @@
 	 * computed.
 	 */
 
-	log = p->to_log & ~s->logs.logwait;
+	log = fe->to_log & ~s->logs.logwait;
 
 	if (s->cli_addr.ss_family == AF_INET)
 		inet_ntop(AF_INET,
@@ -312,8 +316,8 @@
 			  pn, sizeof(pn));
 
 	uri = (log & LW_REQ) ? s->logs.uri ? s->logs.uri : "<BADREQ>" : "";
-	pxid = p->id;
-	srv = (p->to_log & LW_SVID) ?
+	pxid = be->id;
+	srv = (be->to_log & LW_SVID) ?
 		(s->data_source != DATA_SRC_STATS) ?
 		(s->srv != NULL) ? s->srv->id : "<NOSRV>" : "<STATS>" : "-";
 
diff --git a/src/proto_http.c b/src/proto_http.c
index c4afe9c..124594b 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -88,8 +88,8 @@
 	MY_FD_CLR(s->cli_fd, StaticReadEvent);
 	MY_FD_SET(s->cli_fd, StaticWriteEvent);
 	tv_eternity(&s->req->rex);
-	if (s->proxy->clitimeout)
-		tv_delayfrom(&s->rep->wex, &now, s->proxy->clitimeout);
+	if (s->fe->clitimeout)
+		tv_delayfrom(&s->rep->wex, &now, s->fe->clitimeout);
 	else
 		tv_eternity(&s->rep->wex);
 	shutdown(s->cli_fd, SHUT_RD);
@@ -122,7 +122,7 @@
 	t->srv_state = SV_STCLOSE;
 	if (status > 0) {
 		t->logs.status = status;
-		if (t->proxy->mode == PR_MODE_HTTP)
+		if (t->fe->mode == PR_MODE_HTTP)
 			client_return(t, msglen, msg);
 	}
 	if (!(t->flags & SN_ERR_MASK))
@@ -176,12 +176,12 @@
 		return tv_remain2(&now, &t->expire); /* nothing more to do */
 	}
 
-	s->proxy->nbconn--;
+	s->fe->nbconn--;
 	actconn--;
     
 	if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
 		int len;
-		len = sprintf(trash, "%08x:%s.closed[%04x:%04x]\n", s->uniq_id, s->proxy->id, (unsigned short)s->cli_fd, (unsigned short)s->srv_fd);
+		len = sprintf(trash, "%08x:%s.closed[%04x:%04x]\n", s->uniq_id, s->be->id, (unsigned short)s->cli_fd, (unsigned short)s->srv_fd);
 		write(1, trash, len);
 	}
 
@@ -192,7 +192,7 @@
 	/* let's do a final log if we need it */
 	if (s->logs.logwait && 
 	    !(s->flags & SN_MONITOR) &&
-	    (!(s->proxy->options & PR_O_NULLNOLOG) || s->req->total))
+	    (!(s->fe->options & PR_O_NULLNOLOG) || s->req->total))
 		sess_log(s);
 
 	/* the task MUST not be in the run queue anymore */
@@ -281,7 +281,7 @@
 					/* no need to go further */
 					t->logs.status = 403;
 					t->logs.t_request = tv_diff(&t->logs.tv_accept, &now); /* let's log the request time */
-					client_retnclose(t, t->proxy->errmsg.len403, t->proxy->errmsg.msg403);
+					client_retnclose(t, t->fe->errmsg.len403, t->fe->errmsg.msg403);
 					if (!(t->flags & SN_ERR_MASK))
 						t->flags |= SN_ERR_PRXCOND;
 					if (!(t->flags & SN_FINST_MASK))
@@ -299,8 +299,8 @@
 				 * test, we include the leading and trailing spaces in the
 				 * comparison.
 				 */
-				if ((t->proxy->monitor_uri_len != 0) &&
-				    (t->req_line.len >= t->proxy->monitor_uri_len)) {
+				if ((t->be->monitor_uri_len != 0) &&
+				    (t->req_line.len >= t->be->monitor_uri_len)) {
 					char *p = t->req_line.str;
 					int idx = 0;
 
@@ -309,8 +309,8 @@
 						idx++;
 					p += idx;
 
-					if (t->req_line.len - idx >= t->proxy->monitor_uri_len &&
-					    !memcmp(p, t->proxy->monitor_uri, t->proxy->monitor_uri_len)) {
+					if (t->req_line.len - idx >= t->be->monitor_uri_len &&
+					    !memcmp(p, t->be->monitor_uri, t->be->monitor_uri_len)) {
 						/*
 						 * We have found the monitor URI
 						 */
@@ -325,10 +325,10 @@
 					}
 				}
 
-				if (t->proxy->uri_auth != NULL
-				    && t->req_line.len >= t->proxy->uri_auth->uri_len + 4) {   /* +4 for "GET /" */
+				if (t->fi->uri_auth != NULL
+				    && t->req_line.len >= t->fi->uri_auth->uri_len + 4) {   /* +4 for "GET /" */
 					if (!memcmp(t->req_line.str + 4,
-						    t->proxy->uri_auth->uri_prefix, t->proxy->uri_auth->uri_len)
+						    t->fi->uri_auth->uri_prefix, t->fi->uri_auth->uri_len)
 					    && !memcmp(t->req_line.str, "GET ", 4)) {
 						struct user_auth *user;
 						int authenticated;
@@ -336,7 +336,7 @@
 						/* we are in front of a interceptable URI. Let's check
 						 * if there's an authentication and if it's valid.
 						 */
-						user = t->proxy->uri_auth->users;
+						user = t->fi->uri_auth->users;
 						if (!user) {
 							/* no user auth required, it's OK */
 							authenticated = 1;
@@ -364,7 +364,7 @@
 
 							/* no need to go further */
 
-							msglen = sprintf(trash, HTTP_401_fmt, t->proxy->uri_auth->auth_realm);
+							msglen = sprintf(trash, HTTP_401_fmt, t->fi->uri_auth->auth_realm);
 							t->logs.status = 401;
 							client_retnclose(t, msglen, trash);
 							if (!(t->flags & SN_ERR_MASK))
@@ -385,12 +385,12 @@
 				}
 
 
-				for (line = 0; line < t->proxy->nb_reqadd; line++) {
-					len = sprintf(trash, "%s\r\n", t->proxy->req_add[line]);
+				for (line = 0; line < t->fi->nb_reqadd; line++) {
+					len = sprintf(trash, "%s\r\n", t->fi->req_add[line]);
 					buffer_replace2(req, req->h, req->h, trash, len);
 				}
 
-				if (t->proxy->options & PR_O_FWDFOR) {
+				if (t->be->options & PR_O_FWDFOR) {
 					if (t->cli_addr.ss_family == AF_INET) {
 						unsigned char *pn;
 						pn = (unsigned char *)&((struct sockaddr_in *)&t->cli_addr)->sin_addr;
@@ -409,7 +409,7 @@
 				}
 
 				/* add a "connection: close" line if needed */
-				if (t->proxy->options & PR_O_HTTP_CLOSE)
+				if (t->fe->options & PR_O_HTTP_CLOSE)
 					buffer_replace2(req, req->h, req->h, "Connection: close\r\n", 19);
 
 				if (!memcmp(req->data, "POST ", 5)) {
@@ -438,8 +438,8 @@
 				 */
 				//break;
 
-				if (!t->proxy->clitimeout ||
-				    (t->srv_state < SV_STDATA && t->proxy->srvtimeout))
+				if (!t->fe->clitimeout ||
+				    (t->srv_state < SV_STDATA && t->be->srvtimeout))
 					/* If the client has no timeout, or if the server is not ready yet,
 					 * and we know for sure that it can expire, then it's cleaner to
 					 * disable the timeout on the client side so that too low values
@@ -463,7 +463,7 @@
 					 * if the client closes first.
 					 */
 					tv_delayfrom(&req->cex, &now,
-						     t->proxy->contimeout ? t->proxy->contimeout : 0);
+						     t->be->contimeout ? t->be->contimeout : 0);
 				}
 
 				goto process_data;
@@ -518,7 +518,7 @@
 			 *   req->r  = end of data (not used at this stage)
 			 */
 
-			if (!method_checked && (t->proxy->appsession_name != NULL) &&
+			if (!method_checked && (t->be->appsession_name != NULL) &&
 			    ((memcmp(req->h, "GET ", 4) == 0) || (memcmp(req->h, "POST ", 4) == 0)) &&
 			    ((request_line = memchr(req->h, ';', req->lr - req->h)) != NULL)) {
 
@@ -527,42 +527,42 @@
 
 				/* look if we have a jsessionid */
 
-				if (strncasecmp(request_line, t->proxy->appsession_name, t->proxy->appsession_name_len) == 0) {
+				if (strncasecmp(request_line, t->be->appsession_name, t->be->appsession_name_len) == 0) {
 
 					/* skip jsessionid= */
-					request_line += t->proxy->appsession_name_len + 1;
+					request_line += t->be->appsession_name_len + 1;
 		
 					/* First try if we allready have an appsession */
 					asession_temp = &local_asession;
 		
 					if ((asession_temp->sessid = pool_alloc_from(apools.sessid, apools.ses_msize)) == NULL) {
 						Alert("Not enough memory process_cli():asession_temp->sessid:calloc().\n");
-						send_log(t->proxy, LOG_ALERT, "Not enough Memory process_cli():asession_temp->sessid:calloc().\n");
+						send_log(t->be, LOG_ALERT, "Not enough Memory process_cli():asession_temp->sessid:calloc().\n");
 						return 0;
 					}
 
 					/* Copy the sessionid */
-					memcpy(asession_temp->sessid, request_line, t->proxy->appsession_len);
-					asession_temp->sessid[t->proxy->appsession_len] = 0;
+					memcpy(asession_temp->sessid, request_line, t->be->appsession_len);
+					asession_temp->sessid[t->be->appsession_len] = 0;
 					asession_temp->serverid = NULL;
 
 					/* only do insert, if lookup fails */
-					if (chtbl_lookup(&(t->proxy->htbl_proxy), (void *)&asession_temp)) {
+					if (chtbl_lookup(&(t->be->htbl_proxy), (void *)&asession_temp)) {
 						if ((asession_temp = pool_alloc(appsess)) == NULL) {
 							Alert("Not enough memory process_cli():asession:calloc().\n");
-							send_log(t->proxy, LOG_ALERT, "Not enough memory process_cli():asession:calloc().\n");
+							send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession:calloc().\n");
 							return 0;
 						}
 						asession_temp->sessid = local_asession.sessid;
 						asession_temp->serverid = local_asession.serverid;
-						chtbl_insert(&(t->proxy->htbl_proxy), (void *) asession_temp);
+						chtbl_insert(&(t->be->htbl_proxy), (void *) asession_temp);
 					} /* end if (chtbl_lookup()) */
 					else {
 						/*free wasted memory;*/
 						pool_free_to(apools.sessid, local_asession.sessid);
 					}
 
-					tv_delayfrom(&asession_temp->expire, &now, t->proxy->appsession_timeout);
+					tv_delayfrom(&asession_temp->expire, &now, t->be->appsession_timeout);
 					asession_temp->request_count++;
 		
 #if defined(DEBUG_HASH)
@@ -572,10 +572,10 @@
 					if (asession_temp->serverid == NULL) {
 						Alert("Found Application Session without matching server.\n");
 					} else {
-						struct server *srv = t->proxy->srv;
+						struct server *srv = t->be->srv;
 						while (srv) {
 							if (strcmp(srv->id, asession_temp->serverid) == 0) {
-								if (srv->state & SRV_RUNNING || t->proxy->options & PR_O_PERSIST) {
+								if (srv->state & SRV_RUNNING || t->be->options & PR_O_PERSIST) {
 		                /* we found the server and it's usable */
 									t->flags &= ~SN_CK_MASK;
 									t->flags |= SN_CK_VALID | SN_DIRECT | SN_ASSIGNED;
@@ -606,7 +606,7 @@
 				if ((t->logs.uri = pool_alloc(requri)) == NULL) {
 					Alert("HTTP logging : out of memory.\n");
 					t->logs.status = 500;
-					client_retnclose(t, t->proxy->errmsg.len500, t->proxy->errmsg.msg500);
+					client_retnclose(t, t->fe->errmsg.len500, t->fe->errmsg.msg500);
 					if (!(t->flags & SN_ERR_MASK))
 						t->flags |= SN_ERR_PRXCOND;
 					if (!(t->flags & SN_FINST_MASK))
@@ -626,7 +626,7 @@
 			else if (t->logs.logwait & LW_REQHDR) {
 				struct cap_hdr *h;
 				int len;
-				for (h = t->proxy->req_cap; h; h = h->next) {
+				for (h = t->fi->req_cap; h; h = h->next) {
 					if ((h->namelen + 2 <= ptr - req->h) &&
 					    (req->h[h->namelen] == ':') &&
 					    (strncasecmp(req->h, h->name, h->namelen) == 0)) {
@@ -649,7 +649,7 @@
 
 			if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
 				int len, max;
-				len = sprintf(trash, "%08x:%s.clihdr[%04x:%04x]: ", t->uniq_id, t->proxy->id, (unsigned  short)t->cli_fd, (unsigned short)t->srv_fd);
+				len = sprintf(trash, "%08x:%s.clihdr[%04x:%04x]: ", t->uniq_id, t->be->id, (unsigned  short)t->cli_fd, (unsigned short)t->srv_fd);
 				max = ptr - req->h;
 				UBOUND(max, sizeof(trash) - len - 1);
 				len += strlcpy2(trash + len, req->h, max + 1);
@@ -659,20 +659,20 @@
 
 
 			/* remove "connection: " if needed */
-			if (!delete_header && (t->proxy->options & PR_O_HTTP_CLOSE)
+			if (!delete_header && (t->fe->options & PR_O_HTTP_CLOSE)
 			    && (strncasecmp(req->h, "Connection: ", 12) == 0)) {
 				delete_header = 1;
 			}
 
 			/* try headers regexps */
-			if (!delete_header && t->proxy->req_exp != NULL
+			if (!delete_header && t->fi->req_exp != NULL
 			    && !(t->flags & SN_CLDENY)) {
 				struct hdr_exp *exp;
 				char term;
 		
 				term = *ptr;
 				*ptr = '\0';
-				exp = t->proxy->req_exp;
+				exp = t->fi->req_exp;
 				do {
 					if (regexec(exp->preg, req->h, MAX_MATCH, pmatch, 0) == 0) {
 						switch (exp->action) {
@@ -721,7 +721,7 @@
 			 * *MUST* delete it
 			 */
 			if (!delete_header &&
-			    (t->proxy->cookie_name != NULL || t->proxy->capture_name != NULL || t->proxy->appsession_name !=NULL)
+			    (t->be->cookie_name != NULL || t->be->appsession_name !=NULL || t->fi->capture_name != NULL)
 			    && !(t->flags & (SN_CLDENY|SN_CLTARPIT)) && (ptr >= req->h + 8)
 			    && (strncasecmp(req->h, "Cookie: ", 8) == 0)) {
 				char *p1, *p2, *p3, *p4;
@@ -782,26 +782,26 @@
 					}
 					else {
 						/* first, let's see if we want to capture it */
-						if (t->proxy->capture_name != NULL &&
+						if (t->fi->capture_name != NULL &&
 						    t->logs.cli_cookie == NULL &&
-						    (p4 - p1 >= t->proxy->capture_namelen) &&
-						    memcmp(p1, t->proxy->capture_name, t->proxy->capture_namelen) == 0) {
+						    (p4 - p1 >= t->fi->capture_namelen) &&
+						    memcmp(p1, t->fi->capture_name, t->fi->capture_namelen) == 0) {
 							int log_len = p4 - p1;
 
 							if ((t->logs.cli_cookie = pool_alloc(capture)) == NULL) {
 								Alert("HTTP logging : out of memory.\n");
 							} else {
-								if (log_len > t->proxy->capture_len)
-									log_len = t->proxy->capture_len;
+								if (log_len > t->fi->capture_len)
+									log_len = t->fi->capture_len;
 								memcpy(t->logs.cli_cookie, p1, log_len);
 								t->logs.cli_cookie[log_len] = 0;
 							}
 						}
 
-						if ((p2 - p1 == t->proxy->cookie_len) && (t->proxy->cookie_name != NULL) &&
-						    (memcmp(p1, t->proxy->cookie_name, p2 - p1) == 0)) {
+						if ((p2 - p1 == t->be->cookie_len) && (t->be->cookie_name != NULL) &&
+						    (memcmp(p1, t->be->cookie_name, p2 - p1) == 0)) {
 							/* Cool... it's the right one */
-							struct server *srv = t->proxy->srv;
+							struct server *srv = t->be->srv;
 							char *delim;
 
 							/* if we're in cookie prefix mode, we'll search the delimitor so that we
@@ -819,7 +819,7 @@
 							 * +------------------------> req->h
 							 */
 
-							if (t->proxy->options & PR_O_COOK_PFX) {
+							if (t->be->options & PR_O_COOK_PFX) {
 								for (delim = p3; delim < p4; delim++)
 									if (*delim == COOKIE_DELIM)
 										break;
@@ -840,7 +840,7 @@
 
 							while (srv) {
 								if ((srv->cklen == delim - p3) && !memcmp(p3, srv->cookie, delim - p3)) {
-									if (srv->state & SRV_RUNNING || t->proxy->options & PR_O_PERSIST) {
+									if (srv->state & SRV_RUNNING || t->be->options & PR_O_PERSIST) {
 										/* we found the server and it's usable */
 										t->flags &= ~SN_CK_MASK;
 										t->flags |= SN_CK_VALID | SN_DIRECT | SN_ASSIGNED;
@@ -868,7 +868,7 @@
 							 *   application cookie so that it does not get accidentely removed later,
 							 *   if we're in cookie prefix mode
 							 */
-							if ((t->proxy->options & PR_O_COOK_PFX) && (delim != p4)) {
+							if ((t->be->options & PR_O_COOK_PFX) && (delim != p4)) {
 								buffer_replace2(req, p3, delim + 1, NULL, 0);
 								p4  -= (delim + 1 - p3);
 								ptr -= (delim + 1 - p3);
@@ -876,7 +876,7 @@
 								app_cookies++;	/* protect the header from deletion */
 							}
 							else if (del_cookie == NULL &&
-								 (t->proxy->options & (PR_O_COOK_INS | PR_O_COOK_IND)) == (PR_O_COOK_INS | PR_O_COOK_IND)) {
+								 (t->be->options & (PR_O_COOK_INS | PR_O_COOK_IND)) == (PR_O_COOK_INS | PR_O_COOK_IND)) {
 								del_cookie = p1;
 								del_colon = colon;
 							}
@@ -896,8 +896,8 @@
 							}
 						}
 			
-						if ((t->proxy->appsession_name != NULL) &&
-						    (memcmp(p1, t->proxy->appsession_name, p2 - p1) == 0)) {
+						if ((t->be->appsession_name != NULL) &&
+						    (memcmp(p1, t->be->appsession_name, p2 - p1) == 0)) {
 							/* first, let's see if the cookie is our appcookie*/
 			    
 							/* Cool... it's the right one */
@@ -906,25 +906,25 @@
 			  
 							if ((asession_temp->sessid = pool_alloc_from(apools.sessid, apools.ses_msize)) == NULL) {
 								Alert("Not enough memory process_cli():asession->sessid:malloc().\n");
-								send_log(t->proxy, LOG_ALERT, "Not enough memory process_cli():asession->sessid:malloc().\n");
+								send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession->sessid:malloc().\n");
 								return 0;
 							}
 			  
-							memcpy(asession_temp->sessid, p3, t->proxy->appsession_len);
-							asession_temp->sessid[t->proxy->appsession_len] = 0;
+							memcpy(asession_temp->sessid, p3, t->be->appsession_len);
+							asession_temp->sessid[t->be->appsession_len] = 0;
 							asession_temp->serverid = NULL;
 			    
 							/* only do insert, if lookup fails */
-							if (chtbl_lookup(&(t->proxy->htbl_proxy), (void *) &asession_temp) != 0) {
+							if (chtbl_lookup(&(t->be->htbl_proxy), (void *) &asession_temp) != 0) {
 								if ((asession_temp = pool_alloc(appsess)) == NULL) {
 									Alert("Not enough memory process_cli():asession:calloc().\n");
-									send_log(t->proxy, LOG_ALERT, "Not enough memory process_cli():asession:calloc().\n");
+									send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession:calloc().\n");
 									return 0;
 								}
 				
 								asession_temp->sessid = local_asession.sessid;
 								asession_temp->serverid = local_asession.serverid;
-								chtbl_insert(&(t->proxy->htbl_proxy), (void *) asession_temp);
+								chtbl_insert(&(t->be->htbl_proxy), (void *) asession_temp);
 							} else {
 								/* free wasted memory */
 								pool_free_to(apools.sessid, local_asession.sessid);
@@ -933,10 +933,10 @@
 							if (asession_temp->serverid == NULL) {
 								Alert("Found Application Session without matching server.\n");
 							} else {
-								struct server *srv = t->proxy->srv;
+								struct server *srv = t->be->srv;
 								while (srv) {
 									if (strcmp(srv->id, asession_temp->serverid) == 0) {
-										if (srv->state & SRV_RUNNING || t->proxy->options & PR_O_PERSIST) {
+										if (srv->state & SRV_RUNNING || t->be->options & PR_O_PERSIST) {
 											/* we found the server and it's usable */
 											t->flags &= ~SN_CK_MASK;
 											t->flags |= SN_CK_VALID | SN_DIRECT | SN_ASSIGNED;
@@ -951,7 +951,7 @@
 								}/* end while(srv) */
 							}/* end else if server == NULL */
 			    
-							tv_delayfrom(&asession_temp->expire, &now, t->proxy->appsession_timeout);
+							tv_delayfrom(&asession_temp->expire, &now, t->be->appsession_timeout);
 						}/* end if ((t->proxy->appsession_name != NULL) ... */
 					}
 
@@ -995,7 +995,7 @@
 
 				/* We might also need the 'Authorization: ' header */
 				if (t->auth_hdr.len < 0 &&
-				    t->proxy->uri_auth != NULL &&
+				    t->fi->uri_auth != NULL &&
 				    ptr > req->h + 15 &&
 				    !strncasecmp("Authorization: ", req->h, 15)) {
 					t->auth_hdr.str = req->h;
@@ -1014,8 +1014,8 @@
 			 * req->l == rlim-data
 			 */
 			MY_FD_SET(t->cli_fd, StaticReadEvent);
-			if (t->proxy->clitimeout)
-				tv_delayfrom(&req->rex, &now, t->proxy->clitimeout);
+			if (t->fe->clitimeout)
+				tv_delayfrom(&req->rex, &now, t->fe->clitimeout);
 			else
 				tv_eternity(&req->rex);
 		}
@@ -1025,7 +1025,7 @@
 		 */
 		if (req->l >= req->rlim - req->data) {
 			t->logs.status = 400;
-			client_retnclose(t, t->proxy->errmsg.len400, t->proxy->errmsg.msg400);
+			client_retnclose(t, t->fe->errmsg.len400, t->fe->errmsg.msg400);
 			if (!(t->flags & SN_ERR_MASK))
 				t->flags |= SN_ERR_PRXCOND;
 			if (!(t->flags & SN_FINST_MASK))
@@ -1048,7 +1048,7 @@
 			/* read timeout : give up with an error message.
 			 */
 			t->logs.status = 408;
-			client_retnclose(t, t->proxy->errmsg.len408, t->proxy->errmsg.msg408);
+			client_retnclose(t, t->fe->errmsg.len408, t->fe->errmsg.msg408);
 			if (!(t->flags & SN_ERR_MASK))
 				t->flags |= SN_ERR_CLITO;
 			if (!(t->flags & SN_FINST_MASK))
@@ -1099,8 +1099,8 @@
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			MY_FD_SET(t->cli_fd, StaticReadEvent);
-			if (t->proxy->clitimeout)
-				tv_delayfrom(&req->rex, &now, t->proxy->clitimeout);
+			if (t->fe->clitimeout)
+				tv_delayfrom(&req->rex, &now, t->fe->clitimeout);
 			t->cli_state = CL_STSHUTW;
 			//fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
 			return 1;
@@ -1131,8 +1131,8 @@
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			MY_FD_SET(t->cli_fd, StaticReadEvent);
-			if (t->proxy->clitimeout)
-				tv_delayfrom(&req->rex, &now, t->proxy->clitimeout);
+			if (t->fe->clitimeout)
+				tv_delayfrom(&req->rex, &now, t->fe->clitimeout);
 
 			t->cli_state = CL_STSHUTW;
 			if (!(t->flags & SN_ERR_MASK))
@@ -1159,8 +1159,8 @@
 			/* there's still some space in the buffer */
 			if (! MY_FD_ISSET(t->cli_fd, StaticReadEvent)) {
 				MY_FD_SET(t->cli_fd, StaticReadEvent);
-				if (!t->proxy->clitimeout ||
-				    (t->srv_state < SV_STDATA && t->proxy->srvtimeout))
+				if (!t->fe->clitimeout ||
+				    (t->srv_state < SV_STDATA && t->be->srvtimeout))
 					/* If the client has no timeout, or if the server not ready yet, and we
 					 * know for sure that it can expire, then it's cleaner to disable the
 					 * timeout on the client side so that too low values cannot make the
@@ -1168,7 +1168,7 @@
 					 */
 					tv_eternity(&req->rex);
 				else
-					tv_delayfrom(&req->rex, &now, t->proxy->clitimeout);
+					tv_delayfrom(&req->rex, &now, t->fe->clitimeout);
 			}
 		}
 
@@ -1182,8 +1182,8 @@
 			/* buffer not empty */
 			if (! MY_FD_ISSET(t->cli_fd, StaticWriteEvent)) {
 				MY_FD_SET(t->cli_fd, StaticWriteEvent); /* restart writing */
-				if (t->proxy->clitimeout) {
-					tv_delayfrom(&rep->wex, &now, t->proxy->clitimeout);
+				if (t->fe->clitimeout) {
+					tv_delayfrom(&rep->wex, &now, t->fe->clitimeout);
 					/* FIXME: to prevent the client from expiring read timeouts during writes,
 					 * we refresh it. */
 					req->rex = rep->wex;
@@ -1255,8 +1255,8 @@
 			/* buffer not empty */
 			if (! MY_FD_ISSET(t->cli_fd, StaticWriteEvent)) {
 				MY_FD_SET(t->cli_fd, StaticWriteEvent); /* restart writing */
-				if (t->proxy->clitimeout) {
-					tv_delayfrom(&rep->wex, &now, t->proxy->clitimeout);
+				if (t->fe->clitimeout) {
+					tv_delayfrom(&rep->wex, &now, t->fe->clitimeout);
 					/* FIXME: to prevent the client from expiring read timeouts during writes,
 					 * we refresh it. */
 					req->rex = rep->wex;
@@ -1323,8 +1323,8 @@
 			/* there's still some space in the buffer */
 			if (! MY_FD_ISSET(t->cli_fd, StaticReadEvent)) {
 				MY_FD_SET(t->cli_fd, StaticReadEvent);
-				if (t->proxy->clitimeout)
-					tv_delayfrom(&req->rex, &now, t->proxy->clitimeout);
+				if (t->fe->clitimeout)
+					tv_delayfrom(&req->rex, &now, t->fe->clitimeout);
 				else
 					tv_eternity(&req->rex);
 				//fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
@@ -1335,7 +1335,7 @@
 	else { /* CL_STCLOSE: nothing to do */
 		if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
 			int len;
-			len = sprintf(trash, "%08x:%s.clicls[%04x:%04x]\n", t->uniq_id, t->proxy->id, (unsigned short)t->cli_fd, (unsigned short)t->srv_fd);
+			len = sprintf(trash, "%08x:%s.clicls[%04x:%04x]\n", t->uniq_id, t->be->id, (unsigned short)t->cli_fd, (unsigned short)t->srv_fd);
 			write(1, trash, len);
 		}
 		return 0;
@@ -1370,7 +1370,7 @@
 			return 0;	/* stay in idle, waiting for data to reach the client side */
 		else if (c == CL_STCLOSE || c == CL_STSHUTW ||
 			 (c == CL_STSHUTR &&
-			  (t->req->l == 0 || t->proxy->options & PR_O_ABRT_CLOSE))) { /* give up */
+			  (t->req->l == 0 || t->be->options & PR_O_ABRT_CLOSE))) { /* give up */
 			tv_eternity(&req->cex);
 			if (t->pend_pos)
 				t->logs.t_queue = tv_diff(&t->logs.tv_accept, &now);
@@ -1402,7 +1402,7 @@
 				tv_eternity(&req->cex);
 				t->logs.t_queue = tv_diff(&t->logs.tv_accept, &now);
 				srv_close_with_err(t, SN_ERR_PRXCOND, SN_FINST_T,
-						   500, t->proxy->errmsg.len500, t->proxy->errmsg.msg500);
+						   500, t->fe->errmsg.len500, t->fe->errmsg.msg500);
 				return 1;
 			}
 
@@ -1419,10 +1419,10 @@
 					tv_eternity(&req->cex);
 					t->logs.t_queue = tv_diff(&t->logs.tv_accept, &now);
 					srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_Q,
-							   503, t->proxy->errmsg.len503, t->proxy->errmsg.msg503);
+							   503, t->fe->errmsg.len503, t->fe->errmsg.msg503);
 					if (t->srv)
 						t->srv->failed_conns++;
-					t->proxy->failed_conns++;
+					t->fe->failed_conns++;
 					return 1;
 				}
 			}
@@ -1446,7 +1446,7 @@
 	else if (s == SV_STCONN) { /* connection in progress */
 		if (c == CL_STCLOSE || c == CL_STSHUTW ||
 		    (c == CL_STSHUTR &&
-		     (t->req->l == 0 || t->proxy->options & PR_O_ABRT_CLOSE))) { /* give up */
+		     (t->req->l == 0 || t->be->options & PR_O_ABRT_CLOSE))) { /* give up */
 			tv_eternity(&req->cex);
 			fd_delete(t->srv_fd);
 			if (t->srv)
@@ -1479,17 +1479,17 @@
 			if (srv_count_retry_down(t, conn_err))
 				return 1;
 
-			if (t->srv && t->conn_retries == 0 && t->proxy->options & PR_O_REDISP) {
+			if (t->srv && t->conn_retries == 0 && t->be->options & PR_O_REDISP) {
 				/* We're on our last chance, and the REDISP option was specified.
 				 * We will ignore cookie and force to balance or use the dispatcher.
 				 */
 				/* let's try to offer this slot to anybody */
-				if (may_dequeue_tasks(t->srv, t->proxy))
+				if (may_dequeue_tasks(t->srv, t->be))
 					task_wakeup(&rq, t->srv->queue_mgt);
 
 				if (t->srv)
 					t->srv->failed_conns++;
-				t->proxy->failed_conns++;
+				t->be->failed_conns++;
 
 				t->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
 				t->srv = NULL; /* it's left to the dispatcher to choose a server */
@@ -1528,8 +1528,8 @@
 				tv_eternity(&req->wex);
 			} else  /* need the right to write */ {
 				MY_FD_SET(t->srv_fd, StaticWriteEvent);
-				if (t->proxy->srvtimeout) {
-					tv_delayfrom(&req->wex, &now, t->proxy->srvtimeout);
+				if (t->be->srvtimeout) {
+					tv_delayfrom(&req->wex, &now, t->be->srvtimeout);
 					/* FIXME: to prevent the server from expiring read timeouts during writes,
 					 * we refresh it. */
 					rep->rex = req->wex;
@@ -1538,10 +1538,10 @@
 					tv_eternity(&req->wex);
 			}
 
-			if (t->proxy->mode == PR_MODE_TCP) { /* let's allow immediate data connection in this case */
+			if (t->be->mode == PR_MODE_TCP) { /* let's allow immediate data connection in this case */
 				MY_FD_SET(t->srv_fd, StaticReadEvent);
-				if (t->proxy->srvtimeout)
-					tv_delayfrom(&rep->rex, &now, t->proxy->srvtimeout);
+				if (t->be->srvtimeout)
+					tv_delayfrom(&rep->rex, &now, t->be->srvtimeout);
 				else
 					tv_eternity(&rep->rex);
 		
@@ -1552,7 +1552,7 @@
 
 				/* if the user wants to log as soon as possible, without counting
 				   bytes from the server, then this is the right moment. */
-				if (t->proxy->to_log && !(t->logs.logwait & LW_BYTES)) {
+				if (t->fe->to_log && !(t->logs.logwait & LW_BYTES)) {
 					t->logs.t_close = t->logs.t_connect; /* to get a valid end date */
 					sess_log(t);
 				}
@@ -1588,7 +1588,7 @@
 				if (t->flags & SN_CACHEABLE) {
 					if ((t->flags & SN_CACHE_COOK) &&
 					    (t->flags & SN_SCK_ANY) &&
-					    (t->proxy->options & PR_O_CHK_CACHE)) {
+					    (t->be->options & PR_O_CHK_CACHE)) {
 
 						/* we're in presence of a cacheable response containing
 						 * a set-cookie header. We'll block it as requested by
@@ -1601,22 +1601,22 @@
 							t->srv->cur_sess--;
 							t->srv->failed_secu++;
 						}
-						t->proxy->failed_secu++;
+						t->be->failed_secu++;
 						t->srv_state = SV_STCLOSE;
 						t->logs.status = 502;
-						client_return(t, t->proxy->errmsg.len502, t->proxy->errmsg.msg502);
+						client_return(t, t->fe->errmsg.len502, t->fe->errmsg.msg502);
 						if (!(t->flags & SN_ERR_MASK))
 							t->flags |= SN_ERR_PRXCOND;
 						if (!(t->flags & SN_FINST_MASK))
 							t->flags |= SN_FINST_H;
 
-						Alert("Blocking cacheable cookie in response from instance %s, server %s.\n", t->proxy->id, t->srv->id);
-						send_log(t->proxy, LOG_ALERT, "Blocking cacheable cookie in response from instance %s, server %s.\n", t->proxy->id, t->srv->id);
+						Alert("Blocking cacheable cookie in response from instance %s, server %s.\n", t->be->id, t->srv->id);
+						send_log(t->be, LOG_ALERT, "Blocking cacheable cookie in response from instance %s, server %s.\n", t->be->id, t->srv->id);
 
 						/* We used to have a free connection slot. Since we'll never use it,
 						 * we have to inform the server that it may be used by another session.
 						 */
-						if (may_dequeue_tasks(t->srv, t->proxy))
+						if (may_dequeue_tasks(t->srv, t->be))
 							task_wakeup(&rq, t->srv->queue_mgt);
 
 						return 1;
@@ -1632,10 +1632,10 @@
 						t->srv->cur_sess--;
 						t->srv->failed_secu++;
 					}
-					t->proxy->failed_secu++;
+					t->be->failed_secu++;
 					t->srv_state = SV_STCLOSE;
 					t->logs.status = 502;
-					client_return(t, t->proxy->errmsg.len502, t->proxy->errmsg.msg502);
+					client_return(t, t->fe->errmsg.len502, t->fe->errmsg.msg502);
 					if (!(t->flags & SN_ERR_MASK))
 						t->flags |= SN_ERR_PRXCOND;
 					if (!(t->flags & SN_FINST_MASK))
@@ -1643,7 +1643,7 @@
 					/* We used to have a free connection slot. Since we'll never use it,
 					 * we have to inform the server that it may be used by another session.
 					 */
-					if (may_dequeue_tasks(t->srv, t->proxy))
+					if (may_dequeue_tasks(t->srv, t->be))
 						task_wakeup(&rq, t->srv->queue_mgt);
 
 					return 1;
@@ -1651,15 +1651,15 @@
 
 				/* we'll have something else to do here : add new headers ... */
 
-				if ((t->srv) && !(t->flags & SN_DIRECT) && (t->proxy->options & PR_O_COOK_INS) &&
-				    (!(t->proxy->options & PR_O_COOK_POST) || (t->flags & SN_POST))) {
+				if ((t->srv) && !(t->flags & SN_DIRECT) && (t->be->options & PR_O_COOK_INS) &&
+				    (!(t->be->options & PR_O_COOK_POST) || (t->flags & SN_POST))) {
 					/* the server is known, it's not the one the client requested, we have to
 					 * insert a set-cookie here, except if we want to insert only on POST
 					 * requests and this one isn't. Note that servers which don't have cookies
 					 * (eg: some backup servers) will return a full cookie removal request.
 					 */
 					len = sprintf(trash, "Set-Cookie: %s=%s; path=/\r\n",
-						      t->proxy->cookie_name,
+						      t->be->cookie_name,
 						      t->srv->cookie ? t->srv->cookie : "; Expires=Thu, 01-Jan-1970 00:00:01 GMT");
 
 					t->flags |= SN_SCK_INSERTED;
@@ -1669,7 +1669,7 @@
 					 * Some caches understand the correct form: 'no-cache="set-cookie"', but
 					 * others don't (eg: apache <= 1.3.26). So we use 'private' instead.
 					 */
-					if (t->proxy->options & PR_O_COOK_NOC)
+					if (t->be->options & PR_O_COOK_NOC)
 						//len += sprintf(newhdr + len, "Cache-control: no-cache=\"set-cookie\"\r\n");
 						len += sprintf(trash + len, "Cache-control: private\r\n");
 
@@ -1680,13 +1680,13 @@
 				}
 
 				/* headers to be added */
-				for (line = 0; line < t->proxy->nb_rspadd; line++) {
-					len = sprintf(trash, "%s\r\n", t->proxy->rsp_add[line]);
+				for (line = 0; line < t->fi->nb_rspadd; line++) {
+					len = sprintf(trash, "%s\r\n", t->fi->rsp_add[line]);
 					buffer_replace2(rep, rep->h, rep->h, trash, len);
 				}
 
 				/* add a "connection: close" line if needed */
-				if (t->proxy->options & PR_O_HTTP_CLOSE)
+				if (t->fe->options & PR_O_HTTP_CLOSE)
 					buffer_replace2(rep, rep->h, rep->h, "Connection: close\r\n", 19);
 
 				t->srv_state = SV_STDATA;
@@ -1697,15 +1697,15 @@
 				 * we close the server's outgoing connection right now.
 				 */
 				if ((req->l == 0) &&
-				    (c == CL_STSHUTR || c == CL_STCLOSE || t->proxy->options & PR_O_FORCE_CLO)) {
+				    (c == CL_STSHUTR || c == CL_STCLOSE || t->be->options & PR_O_FORCE_CLO)) {
 					MY_FD_CLR(t->srv_fd, StaticWriteEvent);
 					tv_eternity(&req->wex);
 
 					/* We must ensure that the read part is still alive when switching
 					 * to shutw */
 					MY_FD_SET(t->srv_fd, StaticReadEvent);
-					if (t->proxy->srvtimeout)
-						tv_delayfrom(&rep->rex, &now, t->proxy->srvtimeout);
+					if (t->be->srvtimeout)
+						tv_delayfrom(&rep->rex, &now, t->be->srvtimeout);
 
 					shutdown(t->srv_fd, SHUT_WR);
 					t->srv_state = SV_STSHUTW;
@@ -1713,7 +1713,7 @@
 
 				/* if the user wants to log as soon as possible, without counting
 				   bytes from the server, then this is the right moment. */
-				if (t->proxy->to_log && !(t->logs.logwait & LW_BYTES)) {
+				if (t->fe->to_log && !(t->logs.logwait & LW_BYTES)) {
 					t->logs.t_close = t->logs.t_data; /* to get a valid end date */
 					t->logs.bytes = rep->h - rep->data;
 					sess_log(t);
@@ -1770,7 +1770,7 @@
 					 *    unless the response includes appropriate
 					 *    Cache-Control or Expires header fields."
 					 */
-					if (!(t->flags & SN_POST) && (t->proxy->options & PR_O_CHK_CACHE))
+					if (!(t->flags & SN_POST) && (t->be->options & PR_O_CHK_CACHE))
 						t->flags |= SN_CACHEABLE | SN_CACHE_COOK;
 					break;
 				default:
@@ -1780,7 +1780,7 @@
 			else if (t->logs.logwait & LW_RSPHDR) {
 				struct cap_hdr *h;
 				int len;
-				for (h = t->proxy->rsp_cap; h; h = h->next) {
+				for (h = t->fi->rsp_cap; h; h = h->next) {
 					if ((h->namelen + 2 <= ptr - rep->h) &&
 					    (rep->h[h->namelen] == ':') &&
 					    (strncasecmp(rep->h, h->name, h->namelen) == 0)) {
@@ -1803,7 +1803,7 @@
 
 			if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
 				int len, max;
-				len = sprintf(trash, "%08x:%s.srvhdr[%04x:%04x]: ", t->uniq_id, t->proxy->id, (unsigned  short)t->cli_fd, (unsigned short)t->srv_fd);
+				len = sprintf(trash, "%08x:%s.srvhdr[%04x:%04x]: ", t->uniq_id, t->be->id, (unsigned  short)t->cli_fd, (unsigned short)t->srv_fd);
 				max = ptr - rep->h;
 				UBOUND(max, sizeof(trash) - len - 1);
 				len += strlcpy2(trash + len, rep->h, max + 1);
@@ -1812,20 +1812,20 @@
 			}
 
 			/* remove "connection: " if needed */
-			if (!delete_header && (t->proxy->options & PR_O_HTTP_CLOSE)
+			if (!delete_header && (t->fe->options & PR_O_HTTP_CLOSE)
 			    && (strncasecmp(rep->h, "Connection: ", 12) == 0)) {
 				delete_header = 1;
 			}
 
 			/* try headers regexps */
-			if (!delete_header && t->proxy->rsp_exp != NULL
+			if (!delete_header && t->fi->rsp_exp != NULL
 			    && !(t->flags & SN_SVDENY)) {
 				struct hdr_exp *exp;
 				char term;
 		
 				term = *ptr;
 				*ptr = '\0';
-				exp = t->proxy->rsp_exp;
+				exp = t->fi->rsp_exp;
 				do {
 					if (regexec(exp->preg, rep->h, MAX_MATCH, pmatch, 0) == 0) {
 						switch (exp->action) {
@@ -1889,7 +1889,7 @@
 
 			/* check for server cookies */
 			if (!delete_header /*&& (t->proxy->options & PR_O_COOK_ANY)*/
-			    && (t->proxy->cookie_name != NULL || t->proxy->capture_name != NULL || t->proxy->appsession_name !=NULL)
+			    && (t->be->cookie_name != NULL || t->fi->capture_name != NULL || t->be->appsession_name !=NULL)
 			    && (strncasecmp(rep->h, "Set-Cookie: ", 12) == 0)) {
 				char *p1, *p2, *p3, *p4;
 		
@@ -1927,24 +1927,24 @@
 					 */
 
 					/* first, let's see if we want to capture it */
-					if (t->proxy->capture_name != NULL &&
+					if (t->fi->capture_name != NULL &&
 					    t->logs.srv_cookie == NULL &&
-					    (p4 - p1 >= t->proxy->capture_namelen) &&
-					    memcmp(p1, t->proxy->capture_name, t->proxy->capture_namelen) == 0) {
+					    (p4 - p1 >= t->fi->capture_namelen) &&
+					    memcmp(p1, t->fi->capture_name, t->fi->capture_namelen) == 0) {
 						int log_len = p4 - p1;
 
 						if ((t->logs.srv_cookie = pool_alloc(capture)) == NULL) {
 							Alert("HTTP logging : out of memory.\n");
 						}
 
-						if (log_len > t->proxy->capture_len)
-							log_len = t->proxy->capture_len;
+						if (log_len > t->fi->capture_len)
+							log_len = t->fi->capture_len;
 						memcpy(t->logs.srv_cookie, p1, log_len);
 						t->logs.srv_cookie[log_len] = 0;
 					}
 
-					if ((p2 - p1 == t->proxy->cookie_len) && (t->proxy->cookie_name != NULL) &&
-					    (memcmp(p1, t->proxy->cookie_name, p2 - p1) == 0)) {
+					if ((p2 - p1 == t->be->cookie_len) && (t->be->cookie_name != NULL) &&
+					    (memcmp(p1, t->be->cookie_name, p2 - p1) == 0)) {
 						/* Cool... it's the right one */
 						t->flags |= SN_SCK_SEEN;
 			
@@ -1952,20 +1952,20 @@
 						 * this occurrence because we'll insert another one later.
 						 * We'll delete it too if the "indirect" option is set and we're in
 						 * a direct access. */
-						if (((t->srv) && (t->proxy->options & PR_O_COOK_INS)) ||
-						    ((t->flags & SN_DIRECT) && (t->proxy->options & PR_O_COOK_IND))) {
+						if (((t->srv) && (t->be->options & PR_O_COOK_INS)) ||
+						    ((t->flags & SN_DIRECT) && (t->be->options & PR_O_COOK_IND))) {
 							/* this header must be deleted */
 							delete_header = 1;
 							t->flags |= SN_SCK_DELETED;
 						}
-						else if ((t->srv) && (t->proxy->options & PR_O_COOK_RW)) {
+						else if ((t->srv) && (t->be->options & PR_O_COOK_RW)) {
 							/* replace bytes p3->p4 with the cookie name associated
 							 * with this server since we know it.
 							 */
 							buffer_replace2(rep, p3, p4, t->srv->cookie, t->srv->cklen);
 							t->flags |= SN_SCK_INSERTED | SN_SCK_DELETED;
 						}
-						else if ((t->srv) && (t->proxy->options & PR_O_COOK_PFX)) {
+						else if ((t->srv) && (t->be->options & PR_O_COOK_PFX)) {
 							/* insert the cookie name associated with this server
 							 * before existing cookie, and insert a delimitor between them..
 							 */
@@ -1977,8 +1977,8 @@
 					}
 
 					/* first, let's see if the cookie is our appcookie*/
-					if ((t->proxy->appsession_name != NULL) &&
-					    (memcmp(p1, t->proxy->appsession_name, p2 - p1) == 0)) {
+					if ((t->be->appsession_name != NULL) &&
+					    (memcmp(p1, t->be->appsession_name, p2 - p1) == 0)) {
 
 						/* Cool... it's the right one */
 
@@ -1987,22 +1987,22 @@
 		      
 						if ((asession_temp->sessid = pool_alloc_from(apools.sessid, apools.ses_msize)) == NULL) {
 							Alert("Not enought Memory process_srv():asession->sessid:malloc().\n");
-							send_log(t->proxy, LOG_ALERT, "Not enought Memory process_srv():asession->sessid:malloc().\n");
+							send_log(t->be, LOG_ALERT, "Not enought Memory process_srv():asession->sessid:malloc().\n");
 						}
-						memcpy(asession_temp->sessid, p3, t->proxy->appsession_len);
-						asession_temp->sessid[t->proxy->appsession_len] = 0;
+						memcpy(asession_temp->sessid, p3, t->be->appsession_len);
+						asession_temp->sessid[t->be->appsession_len] = 0;
 						asession_temp->serverid = NULL;
 
 						/* only do insert, if lookup fails */
-						if (chtbl_lookup(&(t->proxy->htbl_proxy), (void *) &asession_temp) != 0) {
+						if (chtbl_lookup(&(t->be->htbl_proxy), (void *) &asession_temp) != 0) {
 							if ((asession_temp = pool_alloc(appsess)) == NULL) {
 								Alert("Not enought Memory process_srv():asession:calloc().\n");
-								send_log(t->proxy, LOG_ALERT, "Not enought Memory process_srv():asession:calloc().\n");
+								send_log(t->be, LOG_ALERT, "Not enought Memory process_srv():asession:calloc().\n");
 								return 0;
 							}
 							asession_temp->sessid = local_asession.sessid;
 							asession_temp->serverid = local_asession.serverid;
-							chtbl_insert(&(t->proxy->htbl_proxy), (void *) asession_temp);
+							chtbl_insert(&(t->be->htbl_proxy), (void *) asession_temp);
 						}/* end if (chtbl_lookup()) */
 						else {
 							/* free wasted memory */
@@ -2012,7 +2012,7 @@
 						if (asession_temp->serverid == NULL) {
 							if ((asession_temp->serverid = pool_alloc_from(apools.serverid, apools.ser_msize)) == NULL) {
 								Alert("Not enought Memory process_srv():asession->sessid:malloc().\n");
-								send_log(t->proxy, LOG_ALERT, "Not enought Memory process_srv():asession->sessid:malloc().\n");
+								send_log(t->be, LOG_ALERT, "Not enought Memory process_srv():asession->sessid:malloc().\n");
 							}
 							asession_temp->serverid[0] = '\0';
 						}
@@ -2020,10 +2020,10 @@
 						if (asession_temp->serverid[0] == '\0')
 							memcpy(asession_temp->serverid,t->srv->id,server_id_len);
 		      
-						tv_delayfrom(&asession_temp->expire, &now, t->proxy->appsession_timeout);
+						tv_delayfrom(&asession_temp->expire, &now, t->be->appsession_timeout);
 
 #if defined(DEBUG_HASH)
-						print_table(&(t->proxy->htbl_proxy));
+						print_table(&(t->be->htbl_proxy));
 #endif
 						break;
 					}/* end if ((t->proxy->appsession_name != NULL) ... */
@@ -2040,7 +2040,7 @@
 
 			/* check for any set-cookie in case we check for cacheability */
 			if (!delete_header && !(t->flags & SN_SCK_ANY) &&
-			    (t->proxy->options & PR_O_CHK_CACHE) &&
+			    (t->be->options & PR_O_CHK_CACHE) &&
 			    (strncasecmp(rep->h, "Set-Cookie: ", 12) == 0)) {
 				t->flags |= SN_SCK_ANY;
 			}
@@ -2060,8 +2060,8 @@
 			 * rep->l == rlim-data
 			 */
 			MY_FD_SET(t->srv_fd, StaticReadEvent);
-			if (t->proxy->srvtimeout)
-				tv_delayfrom(&rep->rex, &now, t->proxy->srvtimeout);
+			if (t->be->srvtimeout)
+				tv_delayfrom(&rep->rex, &now, t->be->srvtimeout);
 			else
 				tv_eternity(&rep->rex);
 		}
@@ -2075,11 +2075,11 @@
 				t->srv->cur_sess--;
 				t->srv->failed_resp++;
 			}
-			t->proxy->failed_resp++;
+			t->be->failed_resp++;
 
 			t->srv_state = SV_STCLOSE;
 			t->logs.status = 502;
-			client_return(t, t->proxy->errmsg.len502, t->proxy->errmsg.msg502);
+			client_return(t, t->fe->errmsg.len502, t->fe->errmsg.msg502);
 			if (!(t->flags & SN_ERR_MASK))
 				t->flags |= SN_ERR_SRVCL;
 			if (!(t->flags & SN_FINST_MASK))
@@ -2087,7 +2087,7 @@
 			/* We used to have a free connection slot. Since we'll never use it,
 			 * we have to inform the server that it may be used by another session.
 			 */
-			if (may_dequeue_tasks(t->srv, t->proxy))
+			if (may_dequeue_tasks(t->srv, t->be))
 				task_wakeup(&rq, t->srv->queue_mgt);
 
 			return 1;
@@ -2114,10 +2114,10 @@
 				t->srv->cur_sess--;
 				t->srv->failed_resp++;
 			}
-			t->proxy->failed_resp++;
+			t->be->failed_resp++;
 			t->srv_state = SV_STCLOSE;
 			t->logs.status = 504;
-			client_return(t, t->proxy->errmsg.len504, t->proxy->errmsg.msg504);
+			client_return(t, t->fe->errmsg.len504, t->fe->errmsg.msg504);
 			if (!(t->flags & SN_ERR_MASK))
 				t->flags |= SN_ERR_SRVTO;
 			if (!(t->flags & SN_FINST_MASK))
@@ -2125,7 +2125,7 @@
 			/* We used to have a free connection slot. Since we'll never use it,
 			 * we have to inform the server that it may be used by another session.
 			 */
-			if (may_dequeue_tasks(t->srv, t->proxy))
+			if (may_dequeue_tasks(t->srv, t->be))
 				task_wakeup(&rq, t->srv->queue_mgt);
 
 			return 1;
@@ -2145,8 +2145,8 @@
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			MY_FD_SET(t->srv_fd, StaticReadEvent);
-			if (t->proxy->srvtimeout)
-				tv_delayfrom(&rep->rex, &now, t->proxy->srvtimeout);
+			if (t->be->srvtimeout)
+				tv_delayfrom(&rep->rex, &now, t->be->srvtimeout);
 
 			shutdown(t->srv_fd, SHUT_WR);
 			t->srv_state = SV_STSHUTW;
@@ -2164,14 +2164,14 @@
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			MY_FD_SET(t->srv_fd, StaticReadEvent);
-			if (t->proxy->srvtimeout)
-				tv_delayfrom(&rep->rex, &now, t->proxy->srvtimeout);
+			if (t->be->srvtimeout)
+				tv_delayfrom(&rep->rex, &now, t->be->srvtimeout);
 
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			MY_FD_SET(t->srv_fd, StaticReadEvent);
-			if (t->proxy->srvtimeout)
-				tv_delayfrom(&rep->rex, &now, t->proxy->srvtimeout);
+			if (t->be->srvtimeout)
+				tv_delayfrom(&rep->rex, &now, t->be->srvtimeout);
 
 			t->srv_state = SV_STSHUTW;
 			if (!(t->flags & SN_ERR_MASK))
@@ -2190,8 +2190,8 @@
 		else { /* client buffer not empty */
 			if (! MY_FD_ISSET(t->srv_fd, StaticWriteEvent)) {
 				MY_FD_SET(t->srv_fd, StaticWriteEvent); /* restart writing */
-				if (t->proxy->srvtimeout) {
-					tv_delayfrom(&req->wex, &now, t->proxy->srvtimeout);
+				if (t->be->srvtimeout) {
+					tv_delayfrom(&req->wex, &now, t->be->srvtimeout);
 					/* FIXME: to prevent the server from expiring read timeouts during writes,
 					 * we refresh it. */
 					rep->rex = req->wex;
@@ -2219,7 +2219,7 @@
 				t->srv->cur_sess--;
 				t->srv->failed_resp++;
 			}
-			t->proxy->failed_resp++;
+			t->be->failed_resp++;
 			t->srv_state = SV_STCLOSE;
 			if (!(t->flags & SN_ERR_MASK))
 				t->flags |= SN_ERR_SRVCL;
@@ -2228,7 +2228,7 @@
 			/* We used to have a free connection slot. Since we'll never use it,
 			 * we have to inform the server that it may be used by another session.
 			 */
-			if (may_dequeue_tasks(t->srv, t->proxy))
+			if (may_dequeue_tasks(t->srv, t->be))
 				task_wakeup(&rq, t->srv->queue_mgt);
 
 			return 1;
@@ -2250,8 +2250,8 @@
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			MY_FD_SET(t->srv_fd, StaticReadEvent);
-			if (t->proxy->srvtimeout)
-				tv_delayfrom(&rep->rex, &now, t->proxy->srvtimeout);
+			if (t->be->srvtimeout)
+				tv_delayfrom(&rep->rex, &now, t->be->srvtimeout);
 
 			t->srv_state = SV_STSHUTW;
 			return 1;
@@ -2276,8 +2276,8 @@
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
 			MY_FD_SET(t->srv_fd, StaticReadEvent);
-			if (t->proxy->srvtimeout)
-				tv_delayfrom(&rep->rex, &now, t->proxy->srvtimeout);
+			if (t->be->srvtimeout)
+				tv_delayfrom(&rep->rex, &now, t->be->srvtimeout);
 			t->srv_state = SV_STSHUTW;
 			if (!(t->flags & SN_ERR_MASK))
 				t->flags |= SN_ERR_SRVTO;
@@ -2296,8 +2296,8 @@
 		else { /* buffer not empty, there are still data to be transferred */
 			if (! MY_FD_ISSET(t->srv_fd, StaticWriteEvent)) {
 				MY_FD_SET(t->srv_fd, StaticWriteEvent); /* restart writing */
-				if (t->proxy->srvtimeout) {
-					tv_delayfrom(&req->wex, &now, t->proxy->srvtimeout);
+				if (t->be->srvtimeout) {
+					tv_delayfrom(&req->wex, &now, t->be->srvtimeout);
 					/* FIXME: to prevent the server from expiring read timeouts during writes,
 					 * we refresh it. */
 					rep->rex = req->wex;
@@ -2317,8 +2317,8 @@
 		else {
 			if (! MY_FD_ISSET(t->srv_fd, StaticReadEvent)) {
 				MY_FD_SET(t->srv_fd, StaticReadEvent);
-				if (t->proxy->srvtimeout)
-					tv_delayfrom(&rep->rex, &now, t->proxy->srvtimeout);
+				if (t->be->srvtimeout)
+					tv_delayfrom(&rep->rex, &now, t->be->srvtimeout);
 				else
 					tv_eternity(&rep->rex);
 			}
@@ -2335,7 +2335,7 @@
 				t->srv->cur_sess--;
 				t->srv->failed_resp++;
 			}
-			t->proxy->failed_resp++;
+			t->be->failed_resp++;
 			//close(t->srv_fd);
 			t->srv_state = SV_STCLOSE;
 			if (!(t->flags & SN_ERR_MASK))
@@ -2345,7 +2345,7 @@
 			/* We used to have a free connection slot. Since we'll never use it,
 			 * we have to inform the server that it may be used by another session.
 			 */
-			if (may_dequeue_tasks(t->srv, t->proxy))
+			if (may_dequeue_tasks(t->srv, t->be))
 				task_wakeup(&rq, t->srv->queue_mgt);
 
 			return 1;
@@ -2361,7 +2361,7 @@
 			/* We used to have a free connection slot. Since we'll never use it,
 			 * we have to inform the server that it may be used by another session.
 			 */
-			if (may_dequeue_tasks(t->srv, t->proxy))
+			if (may_dequeue_tasks(t->srv, t->be))
 				task_wakeup(&rq, t->srv->queue_mgt);
 
 			return 1;
@@ -2381,7 +2381,7 @@
 			/* We used to have a free connection slot. Since we'll never use it,
 			 * we have to inform the server that it may be used by another session.
 			 */
-			if (may_dequeue_tasks(t->srv, t->proxy))
+			if (may_dequeue_tasks(t->srv, t->be))
 				task_wakeup(&rq, t->srv->queue_mgt);
 
 			return 1;
@@ -2395,8 +2395,8 @@
 		else { /* buffer not empty */
 			if (! MY_FD_ISSET(t->srv_fd, StaticWriteEvent)) {
 				MY_FD_SET(t->srv_fd, StaticWriteEvent); /* restart writing */
-				if (t->proxy->srvtimeout) {
-					tv_delayfrom(&req->wex, &now, t->proxy->srvtimeout);
+				if (t->be->srvtimeout) {
+					tv_delayfrom(&req->wex, &now, t->be->srvtimeout);
 					/* FIXME: to prevent the server from expiring read timeouts during writes,
 					 * we refresh it. */
 					rep->rex = req->wex;
@@ -2416,7 +2416,7 @@
 				t->srv->cur_sess--;
 				t->srv->failed_resp++;
 			}
-			t->proxy->failed_resp++;
+			t->be->failed_resp++;
 			//close(t->srv_fd);
 			t->srv_state = SV_STCLOSE;
 			if (!(t->flags & SN_ERR_MASK))
@@ -2426,7 +2426,7 @@
 			/* We used to have a free connection slot. Since we'll never use it,
 			 * we have to inform the server that it may be used by another session.
 			 */
-			if (may_dequeue_tasks(t->srv, t->proxy))
+			if (may_dequeue_tasks(t->srv, t->be))
 				task_wakeup(&rq, t->srv->queue_mgt);
 
 			return 1;
@@ -2442,7 +2442,7 @@
 			/* We used to have a free connection slot. Since we'll never use it,
 			 * we have to inform the server that it may be used by another session.
 			 */
-			if (may_dequeue_tasks(t->srv, t->proxy))
+			if (may_dequeue_tasks(t->srv, t->be))
 				task_wakeup(&rq, t->srv->queue_mgt);
 
 			return 1;
@@ -2462,7 +2462,7 @@
 			/* We used to have a free connection slot. Since we'll never use it,
 			 * we have to inform the server that it may be used by another session.
 			 */
-			if (may_dequeue_tasks(t->srv, t->proxy))
+			if (may_dequeue_tasks(t->srv, t->be))
 				task_wakeup(&rq, t->srv->queue_mgt);
 
 			return 1;
@@ -2476,8 +2476,8 @@
 		else {
 			if (! MY_FD_ISSET(t->srv_fd, StaticReadEvent)) {
 				MY_FD_SET(t->srv_fd, StaticReadEvent);
-				if (t->proxy->srvtimeout)
-					tv_delayfrom(&rep->rex, &now, t->proxy->srvtimeout);
+				if (t->be->srvtimeout)
+					tv_delayfrom(&rep->rex, &now, t->be->srvtimeout);
 				else
 					tv_eternity(&rep->rex);
 			}
@@ -2487,7 +2487,7 @@
 	else { /* SV_STCLOSE : nothing to do */
 		if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
 			int len;
-			len = sprintf(trash, "%08x:%s.srvcls[%04x:%04x]\n", t->uniq_id, t->proxy->id, (unsigned short)t->cli_fd, (unsigned short)t->srv_fd);
+			len = sprintf(trash, "%08x:%s.srvcls[%04x:%04x]\n", t->uniq_id, t->be->id, (unsigned short)t->cli_fd, (unsigned short)t->srv_fd);
 			write(1, trash, len);
 		}
 		return 0;
@@ -2662,13 +2662,13 @@
 				if (px->state == PR_STSTOPPED)
 					goto next_proxy;
 
-				if (s->proxy->uri_auth && s->proxy->uri_auth->scope) {
+				if (s->fi->uri_auth && s->fi->uri_auth->scope) {
 					/* we have a limited scope, we have to check the proxy name */
 					struct stat_scope *scope;
 					int len;
 
 					len = strlen(px->id);
-					scope = s->proxy->uri_auth->scope;
+					scope = s->fi->uri_auth->scope;
 
 					while (scope) {
 						/* match exact proxy name */
@@ -2676,7 +2676,7 @@
 							break;
 
 						/* match '.' which means 'self' proxy */
-						if (!strcmp(scope->px_id, ".") && px == s->proxy)
+						if (!strcmp(scope->px_id, ".") && px == s->fe)
 							break;
 						scope = scope->next;
 					}
@@ -2887,7 +2887,7 @@
 	else {
 		/* unknown data source */
 		s->logs.status = 500;
-		client_retnclose(s, s->proxy->errmsg.len500, s->proxy->errmsg.msg500);
+		client_retnclose(s, s->fe->errmsg.len500, s->fe->errmsg.msg500);
 		if (!(s->flags & SN_ERR_MASK))
 			s->flags |= SN_ERR_PRXCOND;
 		if (!(s->flags & SN_FINST_MASK))
diff --git a/src/queue.c b/src/queue.c
index 8b37da0..1247d25 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -104,13 +104,13 @@
 		if (sess->srv->nbpend > sess->srv->nbpend_max)
 			sess->srv->nbpend_max = sess->srv->nbpend;
 	} else {
-		LIST_ADDQ(&sess->proxy->pendconns, &p->list);
-		sess->logs.prx_queue_size += sess->proxy->nbpend;
-		sess->proxy->nbpend++;
-		if (sess->proxy->nbpend > sess->proxy->nbpend_max)
-			sess->proxy->nbpend_max = sess->proxy->nbpend;
+		LIST_ADDQ(&sess->be->pendconns, &p->list);
+		sess->logs.prx_queue_size += sess->be->nbpend;
+		sess->be->nbpend++;
+		if (sess->be->nbpend > sess->be->nbpend_max)
+			sess->be->nbpend_max = sess->be->nbpend;
 	}
-	sess->proxy->totpend++;
+	sess->be->totpend++;
 	return p;
 }
 
@@ -126,8 +126,8 @@
 	if (p->srv)
 		p->srv->nbpend--;
 	else
-		p->sess->proxy->nbpend--;
-	p->sess->proxy->totpend--;
+		p->sess->be->nbpend--;
+	p->sess->be->totpend--;
 	pool_free(pendconn, p);
 }
 
diff --git a/src/session.c b/src/session.c
index 9a59e28..16047ea 100644
--- a/src/session.c
+++ b/src/session.c
@@ -41,19 +41,19 @@
 
 	if (s->rsp_cap != NULL) {
 		struct cap_hdr *h;
-		for (h = s->proxy->rsp_cap; h; h = h->next) {
+		for (h = s->fi->rsp_cap; h; h = h->next) {
 			if (s->rsp_cap[h->index] != NULL)
 				pool_free_to(h->pool, s->rsp_cap[h->index]);
 		}
-		pool_free_to(s->proxy->rsp_cap_pool, s->rsp_cap);
+		pool_free_to(s->fi->rsp_cap_pool, s->rsp_cap);
 	}
 	if (s->req_cap != NULL) {
 		struct cap_hdr *h;
-		for (h = s->proxy->req_cap; h; h = h->next) {
+		for (h = s->fi->req_cap; h; h = h->next) {
 			if (s->req_cap[h->index] != NULL)
 				pool_free_to(h->pool, s->req_cap[h->index]);
 		}
-		pool_free_to(s->proxy->req_cap_pool, s->req_cap);
+		pool_free_to(s->fi->req_cap_pool, s->req_cap);
 	}
 
 	if (s->logs.uri)