MINOR: proxy-v2-options: add crc32c

This patch add option crc32c (PP2_TYPE_CRC32C) to proxy protocol v2.
It compute the checksum of proxy protocol v2 header as describe in
"doc/proxy-protocol.txt".
diff --git a/doc/configuration.txt b/doc/configuration.txt
index c2e4435..fc8304c 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -11726,7 +11726,7 @@
   name of the used cipher, "cert-sig": signature algorithm of the used
   certificate, "cert-key": key algorithm of the used certificate), "authority":
   host name value passed by the client (only sni from a tls connection is
-  supported).
+  supported), "crc32c": checksum of the proxy protocol v2 header.
 
 send-proxy-v2-ssl
   The "send-proxy-v2-ssl" parameter enforces use of the PROXY protocol version
diff --git a/include/types/server.h b/include/types/server.h
index 6d0566b..80df8db 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -152,6 +152,7 @@
 #define SRV_PP_V2_SSL_SIG_ALG   0x0020   /* proxy protocol version 2 with cert signature algorithm */
 #define SRV_PP_V2_SSL_CIPHER    0x0040   /* proxy protocol version 2 with cipher used */
 #define SRV_PP_V2_AUTHORITY     0x0080   /* proxy protocol version 2 with authority */
+#define SRV_PP_V2_CRC32C        0x0100   /* proxy protocol version 2 with crc32c */
 
 /* function which act on servers need to return various errors */
 #define SRV_STATUS_OK       0   /* everything is OK. */
@@ -195,7 +196,8 @@
 	enum obj_type obj_type;                 /* object type == OBJ_TYPE_SERVER */
 	enum srv_state next_state, cur_state;   /* server state among SRV_ST_* */
 	enum srv_admin next_admin, cur_admin;   /* server maintenance status : SRV_ADMF_* */
-	unsigned char pp_opts;                  /* proxy protocol options (SRV_PP_*) */
+	/* 1 unused byte here */
+	unsigned int pp_opts;                   /* proxy protocol options (SRV_PP_*) */
 	struct server *next;
 	int cklen;				/* the len of the cookie, to speed up checks */
 	int rdr_len;				/* the length of the redirection prefix */
diff --git a/src/connection.c b/src/connection.c
index 206b22b..db5134e 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -15,6 +15,8 @@
 #include <common/compat.h>
 #include <common/config.h>
 #include <common/namespace.h>
+#include <common/hash.h>
+#include <common/net_helper.h>
 
 #include <proto/connection.h>
 #include <proto/fd.h>
@@ -990,6 +992,7 @@
 int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connection *remote)
 {
 	const char pp2_signature[] = PP2_SIGNATURE;
+	void *tlv_crc32c_p = NULL;
 	int ret = 0;
 	struct proxy_hdr_v2 *hdr = (struct proxy_hdr_v2 *)buf;
 	struct sockaddr_storage null_addr = { .ss_family = 0 };
@@ -1037,6 +1040,14 @@
 		ret = PP2_HDR_LEN_UNSPEC;
 	}
 
+	if (srv->pp_opts & SRV_PP_V2_CRC32C) {
+		uint32_t zero_crc32c = 0;
+		if ((buf_len - ret) < sizeof(struct tlv))
+			return 0;
+		tlv_crc32c_p = (void *)((struct tlv *)&buf[ret])->value;
+		ret += make_tlv(&buf[ret], (buf_len - ret), PP2_TYPE_CRC32C, sizeof(zero_crc32c), (const char *)&zero_crc32c);
+	}
+
 	if (conn_get_alpn(remote, &value, &value_len)) {
 		if ((buf_len - ret) < sizeof(struct tlv))
 			return 0;
@@ -1115,6 +1126,10 @@
 
 	hdr->len = htons((uint16_t)(ret - PP2_HEADER_LEN));
 
+	if (tlv_crc32c_p) {
+		write_u32(tlv_crc32c_p, htonl(hash_crc32c(buf, ret)));
+	}
+
 	return ret;
 }
 
diff --git a/src/server.c b/src/server.c
index f4cf45c..28cc741 100644
--- a/src/server.c
+++ b/src/server.c
@@ -528,6 +528,8 @@
 			newsrv->pp_opts |= SRV_PP_V2_SSL_CIPHER;
 		} else if (!strcmp(p, "authority")) {
 			newsrv->pp_opts |= SRV_PP_V2_AUTHORITY;
+		} else if (!strcmp(p, "crc32c")) {
+			newsrv->pp_opts |= SRV_PP_V2_CRC32C;
 		} else
 			goto fail;
 	}