MEDIUM: connection: Implement and extented PROXY Protocol V2

This commit modifies the PROXY protocol V2 specification to support headers
longer than 255 bytes allowing for optional extensions.  It implements the
PROXY protocol V2 which is a binary representation of V1. This will make
parsing more efficient for clients who will know in advance exactly how
many bytes to read.  Also, it defines and implements some optional PROXY
protocol V2 extensions to send information about downstream SSL/TLS
connections.  Support for PROXY protocol V1 remains unchanged.
diff --git a/include/proto/connection.h b/include/proto/connection.h
index 10bc4d8..c9972b1 100644
--- a/include/proto/connection.h
+++ b/include/proto/connection.h
@@ -41,7 +41,9 @@
 
 /* receive a PROXY protocol header over a connection */
 int conn_recv_proxy(struct connection *conn, int flag);
-int make_proxy_line(char *buf, int buf_len, struct sockaddr_storage *src, struct sockaddr_storage *dst);
+int make_proxy_line(char *buf, int buf_len, struct server *srv, struct connection *remote);
+int make_proxy_line_v1(char *buf, int buf_len, struct sockaddr_storage *src, struct sockaddr_storage *dst);
+int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connection *remote);
 
 /* returns true is the transport layer is ready */
 static inline int conn_xprt_ready(const struct connection *conn)
diff --git a/include/proto/ssl_sock.h b/include/proto/ssl_sock.h
index 9d891d9..2d1dadc 100644
--- a/include/proto/ssl_sock.h
+++ b/include/proto/ssl_sock.h
@@ -32,6 +32,16 @@
 extern int sslconns;
 extern int totalsslconns;
 
+/* boolean, returns true if connection is over SSL */
+static inline
+int ssl_sock_is_ssl(struct connection *conn)
+{
+	if (!conn || conn->xprt != &ssl_sock || !conn->xprt_ctx)
+		return 0;
+	else
+		return 1;
+}
+
 int ssl_sock_handshake(struct connection *conn, unsigned int flag);
 int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *proxy);
 void ssl_sock_free_certs(struct bind_conf *bind_conf);
@@ -40,6 +50,10 @@
 void ssl_sock_free_all_ctx(struct bind_conf *bind_conf);
 const char *ssl_sock_get_cipher_name(struct connection *conn);
 const char *ssl_sock_get_proto_version(struct connection *conn);
+char *ssl_sock_get_version(struct connection *conn);
+int ssl_sock_get_cert_used(struct connection *conn);
+char *ssl_sock_get_common_name(struct connection *conn);
+unsigned int ssl_sock_get_verify_result(struct connection *conn);
 
 #endif /* _PROTO_SSL_SOCK_H */
 
diff --git a/include/types/connection.h b/include/types/connection.h
index 83ac432..4779bc0 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -267,6 +267,77 @@
 	} addr; /* addresses of the remote side, client for producer and server for consumer */
 };
 
+/* proxy protocol v2 definitions */
+#define PP2_SIGNATURE_LEN        12
+#define PP2_HEADER_LEN           16
+#define PP2_VERSION            0x20
+#define PP2_CMD_LOCAL          0x00
+#define PP2_CMD_PROXY          0x01
+#define PP2_FAM_UNSPEC         0x00
+#define PP2_FAM_INET           0x10
+#define PP2_FAM_INET6          0x20
+#define PP2_FAM_UNIX           0x30
+#define PP2_TRANS_UNSPEC       0x00
+#define PP2_TRANS_STREAM       0x01
+#define PP2_TRANS_DGRAM        0x02
+
+#define PP2_ADDR_LEN_UNSPEC       0
+#define PP2_ADDR_LEN_INET        12
+#define PP2_ADDR_LEN_INET6       36
+#define PP2_ADDR_LEN_UNIX       216
+
+#define PP2_HDR_LEN_UNSPEC  (PP2_HEADER_LEN + PP2_ADDR_LEN_UNSPEC)
+#define PP2_HDR_LEN_INET    (PP2_HEADER_LEN + PP2_ADDR_LEN_INET)
+#define PP2_HDR_LEN_INET6   (PP2_HEADER_LEN + PP2_ADDR_LEN_INET6)
+#define PP2_HDR_LEN_UNIX    (PP2_HEADER_LEN + PP2_ADDR_LEN_UNIX)
+
+struct proxy_hdr_v2 {
+	uint8_t sig[12];   /* hex 0D 0A 0D 0A 00 0D 0A 51 55 49 54 0A */
+	uint8_t cmd;       /* protocol version and command */
+	uint8_t fam;       /* protocol family and transport */
+	uint16_t len;      /* number of following bytes part of the header */
+};
+
+union proxy_addr {
+	struct {        /* for TCP/UDP over IPv4, len = 12 */
+		uint32_t src_addr;
+		uint32_t dst_addr;
+		uint16_t src_port;
+		uint16_t dst_port;
+	} ipv4_addr;
+	struct {        /* for TCP/UDP over IPv6, len = 36 */
+		uint8_t  src_addr[16];
+		uint8_t  dst_addr[16];
+		uint16_t src_port;
+		uint16_t dst_port;
+	} ipv6_addr;
+	struct {        /* for AF_UNIX sockets, len = 216 */
+		uint8_t src_addr[108];
+		uint8_t dst_addr[108];
+	} unix_addr;
+};
+
+#define PP2_TYPE_SSL           0x20
+#define PP2_TYPE_SSL_VERSION   0x21
+#define PP2_TYPE_SSL_CN        0x22
+
+struct tlv {
+	uint8_t type;
+	uint8_t length_hi;
+	uint8_t length_lo;
+	uint8_t value[0];
+}__attribute__((packed));
+
+struct tlv_ssl {
+	struct tlv tlv;
+	uint8_t client;
+	uint32_t verify;
+	uint8_t sub_tlv[0];
+}__attribute__((packed));
+
+#define PP2_CLIENT_SSL      0x01
+#define PP2_CLIENT_CERT     0x02
+
 #endif /* _TYPES_CONNECTION_H */
 
 /*
diff --git a/include/types/server.h b/include/types/server.h
index 54ab813..7a977e3 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -53,10 +53,15 @@
 #define SRV_WARMINGUP	0x0040	/* this server is warming up after a failure */
 #define SRV_MAINTAIN	0x0080	/* this server is in maintenance mode */
 #define SRV_DRAIN	0x0100	/* this server has been requested to drain its connections */
-/* unused: 0x0200, 0x0400 */
-#define SRV_SEND_PROXY	0x0800	/* this server talks the PROXY protocol */
+/* unused: 0x0200, 0x0400, 0x0800 */
 #define SRV_NON_STICK	0x1000	/* never add connections allocated to this server to a stick table */
 
+/* configured server options for send-proxy (server->pp_opts) */
+#define SRV_PP_V1          0x0001        /* proxy protocol version 1 */
+#define SRV_PP_V2          0x0002        /* proxy protocol version 2 */
+#define SRV_PP_V2_SSL      0x0004        /* proxy protocol version 2 with SSL*/
+#define SRV_PP_V2_SSL_CN   0x0008        /* proxy protocol version 2 with SSL and CN*/
+
 /* function which act on servers need to return various errors */
 #define SRV_STATUS_OK       0   /* everything is OK. */
 #define SRV_STATUS_INTERNAL 1   /* other unrecoverable errors. */
@@ -106,6 +111,7 @@
 	int rdr_len;				/* the length of the redirection prefix */
 	char *cookie;				/* the id set in the cookie */
 	char *rdr_pfx;				/* the redirection prefix */
+	int pp_opts;				/* proxy protocol options (SRV_PP_*) */
 
 	struct proxy *proxy;			/* the proxy this server belongs to */
 	int served;				/* # of active sessions currently being served (ie not pending) */