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.
This commit is contained in:
Bertrand Jacquin 2017-12-12 01:17:23 +00:00 committed by Willy Tarreau
parent a341a2f479
commit 72fa1ec24e
2 changed files with 51 additions and 17 deletions

View File

@ -10,7 +10,9 @@ Specifications and documentations from NetScaler:
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 @@ the TCP handshake. This is composed as:
- 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.

View File

@ -678,14 +678,8 @@ int conn_recv_proxy(struct connection *conn, int flag)
}
/* 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,24 +729,38 @@ int conn_recv_netscaler_cip(struct connection *conn, int flag)
}
/* 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;
/* Fail if buffer length is not large enough to contain
* CIP magic, CIP length, minimal IP header */
if (trash.len < 28)
goto missing;
/* 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;
}
line += 8;
/* Fail if buffer length is not large enough to contain
* a minimal IP header */
if (trash.len < 20)
goto missing;
/* Get IP version from the first four bits */
ip_v = (*line & 0xf0) >> 4;