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
- 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.
}
/* 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.
}
/* 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;