[MAJOR] support for source binding via cttproxy

Using the cttproxy kernel patch, it's possible to bind to any source
address. It is highly recommended to use the 03-natdel patch with the
other ones.

A new keyword appears as a complement to the "source" keyword : "usesrc".
The source address is mandatory and must be valid on the interface which
will see the packets. The "usesrc" option supports "client" (for full
client_ip:client_port spoofing), "client_ip" (for client_ip spoofing)
and any 'IP[:port]' combination to pretend to be another machine.

Right now, the source binding is missing from server health-checks if
set to another address. It must be implemented (think restricted firewalls).
The doc is still missing too.
diff --git a/src/backend.c b/src/backend.c
index 2884ea5..1813d34 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -35,6 +35,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
@@ -384,6 +387,42 @@
 				 s->proxy->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->proxy->id, s->srv->id);
+				close(fd);
+				send_log(s->proxy, LOG_EMERG,
+					 "Cannot bind to tproxy source address before connect() for server %s/%s.\n",
+					 s->proxy->id, s->srv->id);
+				return SN_ERR_RESOURCE;
+			}
+		}
+#endif
 	}
 	else if (s->proxy->options & PR_O_BIND_SRC) {
 		setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one));
@@ -395,6 +434,42 @@
 				 s->proxy->id, s->srv->id);
 			return SN_ERR_RESOURCE;
 		}
+#ifdef CONFIG_HAP_CTTPROXY
+		if (s->proxy->options & PR_O_TPXY_MASK) {
+			struct in_tproxy itp1, itp2;
+			memset(&itp1, 0, sizeof(itp1));
+
+			itp1.op = TPROXY_ASSIGN;
+			switch (s->proxy->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->proxy->id);
+				close(fd);
+				send_log(s->proxy, LOG_EMERG,
+					 "Cannot bind to tproxy source address before connect() for server %s/%s.\n",
+					 s->proxy->id, s->srv->id);
+				return SN_ERR_RESOURCE;
+			}
+		}
+#endif
 	}
 	
 	if ((connect(fd, (struct sockaddr *)&s->srv_addr, sizeof(s->srv_addr)) == -1) &&