MEDIUM: netscaler: add support for standard NetScaler CIP protocol

It looks like two version of the protocol exist as reported by
Andreas Mahnke. This patch add support for both legacy and standard CIP
protocol according to NetScaler specifications.
diff --git a/doc/netscaler-client-ip-insertion-protocol.txt b/doc/netscaler-client-ip-insertion-protocol.txt
index 6f77f65..559d98a 100644
--- a/doc/netscaler-client-ip-insertion-protocol.txt
+++ b/doc/netscaler-client-ip-insertion-protocol.txt
@@ -10,7 +10,9 @@
   https://www.citrix.com/blogs/2016/04/25/how-to-enable-client-ip-in-tcpip-option-of-netscaler/
 
 When CIP is enabled on the NetScaler, then a TCP packet is inserted just after
-the TCP handshake. This is composed as:
+the TCP handshake. Two versions of the CIP extension exist.
+
+Legacy (NetScaler < 10.5)
 
   - CIP magic number : 4 bytes
     Both sender and receiver have to agree on a magic number so that
@@ -27,3 +29,27 @@
   - TCP header : >= 20 bytes
     Contains the header of the last TCP packet sent by the client during TCP
     handshake.
+
+Standard (NetScaler >= 10.5)
+
+  - CIP magic number : 4 bytes
+    Both sender and receiver have to agree on a magic number so that
+    they both handle the incoming data as a NetScaler Client IP insertion
+    packet.
+
+  - CIP length : 4 bytes
+    Defines the total length on the CIP header.
+
+  - CIP type: 2 bytes
+    Always set to 1.
+
+  - Header length : 2 bytes
+    Defines the length on the remaining data.
+
+  - IP header : >= 20 bytes if IPv4, 40 bytes if IPv6
+    Contains the header of the last IP packet sent by the client during TCP
+    handshake.
+
+  - TCP header : >= 20 bytes
+    Contains the header of the last TCP packet sent by the client during TCP
+    handshake.
diff --git a/src/connection.c b/src/connection.c
index 58bf4a5..0f8acb0 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -678,14 +678,8 @@
 }
 
 /* This handshake handler waits a NetScaler Client IP insertion header
- * at the beginning of the raw data stream. The header looks like this:
- *
- *   4 bytes:   CIP magic number
- *   4 bytes:   Header length
- *   20+ bytes: Header of the last IP packet sent by the client during
- *              TCP handshake.
- *   20+ bytes: Header of the last TCP packet sent by the client during
- *              TCP handshake.
+ * at the beginning of the raw data stream. The header format is
+ * described in doc/netscaler-client-ip-insertion-protocol.txt
  *
  * This line MUST be at the beginning of the buffer and MUST NOT be
  * fragmented.
@@ -735,25 +729,39 @@
 	}
 
 	/* Fail if buffer length is not large enough to contain
-	 * CIP magic, CIP length */
-	if (trash.len < 8)
+	 * CIP magic, header length or
+	 * CIP magic, CIP length, CIP type, header length */
+	if (trash.len < 12)
 		goto missing;
 
 	line = trash.str;
-	hdr_len = ntohl(*(uint32_t *)(line+4));
 
 	/* Decode a possible NetScaler Client IP request, fail early if
 	 * it does not match */
 	if (ntohl(*(uint32_t *)line) != objt_listener(conn->target)->bind_conf->ns_cip_magic)
 		goto bad_magic;
 
+	/* Legacy CIP protocol */
+	if ((trash.str[8] & 0xD0) == 0x40) {
+		hdr_len = ntohl(*(uint32_t *)(line+4));
+		line += 8;
+	}
+	/* Standard CIP protocol */
+	else if (trash.str[8] == 0x00) {
+		hdr_len = ntohs(*(uint32_t *)(line+10));
+		line += 12;
+	}
+	/* Unknown CIP protocol */
+	else {
+		conn->err_code = CO_ER_CIP_BAD_PROTO;
+		goto fail;
+	}
+
 	/* Fail if buffer length is not large enough to contain
-	 * CIP magic, CIP length, minimal IP header */
-	if (trash.len < 28)
+	 * a minimal IP header */
+	if (trash.len < 20)
 		goto missing;
 
-	line += 8;
-
 	/* Get IP version from the first four bits */
 	ip_v = (*line & 0xf0) >> 4;