@@ -583,14 +583,18 @@ static uint32_t crctable[256] = {
583583 0xBE2DA0A5L , 0x4C4623A6L , 0x5F16D052L , 0xAD7D5351L
584584};
585585
586- static uint32_t crc32c ( const uint8_t * buf , uint32_t len )
586+ static uint32_t crc32c_continue ( uint32_t crc , const uint8_t * buf , uint32_t len )
587587{
588- uint32_t crc = 0xffffffff ;
589588 while (len -- > 0 )
590589 {
591590 crc = (crc >> 8 ) ^ crctable [(crc ^ (* buf ++ )) & 0xFF ];
592591 }
593- return crc ^ 0xffffffff ;
592+ return crc ;
593+ }
594+
595+ static uint32_t crc32c (const uint8_t * buf , uint32_t len )
596+ {
597+ return crc32c_continue (0xffffffff , buf , len ) ^ 0xffffffff ;
594598}
595599
596600static uint8_t * pp2_create_hdr (const pp_info_t * pp_info , uint16_t * pp2_hdr_len , int32_t * error )
@@ -844,13 +848,13 @@ uint8_t *pp_create_hdr(uint8_t version, const pp_info_t *pp_info, uint16_t *pp_h
844848}
845849
846850/* Verifies and parses a version 2 PROXY protocol header */
847- static int32_t pp2_parse_hdr (uint8_t * buffer , uint32_t buffer_length , pp_info_t * pp_info )
851+ static int32_t pp2_parse_hdr (const uint8_t * buffer , uint32_t buffer_length , pp_info_t * pp_info )
848852{
849853 const uint8_t * pp2_hdr = buffer ;
850- const proxy_hdr_v2_t * proxy_hdr_v2 = (proxy_hdr_v2_t * ) buffer ;
854+ const proxy_hdr_v2_t * proxy_hdr_v2 = (const proxy_hdr_v2_t * ) buffer ;
851855 uint8_t cmd , fam ;
852856 uint16_t len = 0 , tlv_vectors_len = 0 ;
853- proxy_addr_t * addr = NULL ;
857+ const proxy_addr_t * addr = NULL ;
854858
855859 /* The next byte (the 13th one) is the protocol version and command */
856860 /* The highest four bits contains the version. Only \x2 is accepted */
@@ -924,7 +928,7 @@ static int32_t pp2_parse_hdr(uint8_t *buffer, uint32_t buffer_length, pp_info_t
924928 * - destination layer 4 address if any, in network byte order (port)
925929 */
926930 buffer += sizeof (proxy_hdr_v2_t );
927- addr = (proxy_addr_t * ) buffer ;
931+ addr = (const proxy_addr_t * ) buffer ;
928932 if (fam == AF_UNSPEC )
929933 {
930934 tlv_vectors_len = len ;
@@ -977,7 +981,7 @@ static int32_t pp2_parse_hdr(uint8_t *buffer, uint32_t buffer_length, pp_info_t
977981 /* Any TLV vector must be at least 3 bytes */
978982 while (tlv_vectors_len > sizeof_pp2_tlv_t )
979983 {
980- pp2_tlv_t * pp2_tlv = (pp2_tlv_t * ) buffer ;
984+ const pp2_tlv_t * pp2_tlv = (const pp2_tlv_t * ) buffer ;
981985 uint16_t pp2_tlv_len = pp2_tlv -> length_hi << 8 | pp2_tlv -> length_lo ;
982986 uint16_t pp2_tlv_offset = sizeof_pp2_tlv_t + pp2_tlv_len ;
983987 if (pp2_tlv_offset > tlv_vectors_len )
@@ -996,7 +1000,9 @@ static int32_t pp2_parse_hdr(uint8_t *buffer, uint32_t buffer_length, pp_info_t
9961000 break ;
9971001 case PP2_TYPE_CRC32C : /* 32-bit number */
9981002 {
999- uint32_t crc32c_chksum , crc32c_calculated ;
1003+ uint32_t crc32c_chksum , crc32c_calculated , crc ;
1004+ const uint8_t zeros [4 ] = {0 , 0 , 0 , 0 };
1005+ uint32_t total_hdr_len , offset_to_chksum_value , after_chksum_offset ;
10001006
10011007 if (pp2_tlv_len != sizeof (uint32_t ))
10021008 {
@@ -1006,11 +1012,20 @@ static int32_t pp2_parse_hdr(uint8_t *buffer, uint32_t buffer_length, pp_info_t
10061012 /* Received CRC32c checksum */
10071013 memcpy (& crc32c_chksum , pp2_tlv -> value , pp2_tlv_len );
10081014
1009- /* Calculate the CRC32c checksum value of the whole PROXY header */
1010- memset (pp2_tlv -> value , 0 , pp2_tlv_len );
1011- crc32c_calculated = crc32c (pp2_hdr , sizeof (proxy_hdr_v2_t ) + len );
1015+ /* Calculate the CRC32c checksum value of the whole PROXY header.
1016+ * The checksum is computed with the checksum field treated as zeros.
1017+ * Instead of zeroing the field in the buffer, compute CRC in 3 segments:
1018+ * before the checksum value, 4 zero bytes, after the checksum value. */
1019+ total_hdr_len = sizeof (proxy_hdr_v2_t ) + len ;
1020+ offset_to_chksum_value = (const uint8_t * )pp2_tlv -> value - pp2_hdr ;
1021+ after_chksum_offset = offset_to_chksum_value + sizeof (uint32_t );
1022+
1023+ crc = crc32c_continue (0xffffffff , pp2_hdr , offset_to_chksum_value );
1024+ crc = crc32c_continue (crc , zeros , sizeof (uint32_t ));
1025+ crc = crc32c_continue (crc , pp2_hdr + after_chksum_offset , total_hdr_len - after_chksum_offset );
1026+ crc32c_calculated = crc ^ 0xffffffff ;
10121027
1013- /* Verify that the calculated CRC32c checksum is the same as the received CRC32c checksum*/
1028+ /* Verify that the calculated CRC32c checksum is the same as the received CRC32c checksum */
10141029 if (memcmp (& crc32c_chksum , & crc32c_calculated , 4 ))
10151030 {
10161031 return - ERR_PP2_TYPE_CRC32C ;
@@ -1037,7 +1052,7 @@ static int32_t pp2_parse_hdr(uint8_t *buffer, uint32_t buffer_length, pp_info_t
10371052 break ;
10381053 case PP2_TYPE_SSL :
10391054 {
1040- pp2_tlv_ssl_t * pp2_tlv_ssl = (pp2_tlv_ssl_t * ) pp2_tlv -> value ;
1055+ const pp2_tlv_ssl_t * pp2_tlv_ssl = (const pp2_tlv_ssl_t * ) pp2_tlv -> value ;
10411056 uint16_t pp2_tlvs_ssl_len = 0 , pp2_sub_tlv_offset = 0 ;
10421057 uint8_t tlv_ssl_version_found = 0 ;
10431058
@@ -1050,7 +1065,7 @@ static int32_t pp2_parse_hdr(uint8_t *buffer, uint32_t buffer_length, pp_info_t
10501065 pp2_tlvs_ssl_len = pp2_tlv_len - sizeof (pp2_tlv_ssl -> client ) - sizeof (pp2_tlv_ssl -> verify );
10511066 while (pp2_sub_tlv_offset < pp2_tlvs_ssl_len )
10521067 {
1053- pp2_tlv_t * pp2_sub_tlv_ssl = (pp2_tlv_t * ) ((uint8_t * ) pp2_tlv_ssl -> sub_tlv + pp2_sub_tlv_offset );
1068+ const pp2_tlv_t * pp2_sub_tlv_ssl = (const pp2_tlv_t * ) ((const uint8_t * ) pp2_tlv_ssl -> sub_tlv + pp2_sub_tlv_offset );
10541069 uint16_t pp2_sub_tlv_ssl_len = pp2_sub_tlv_ssl -> length_hi << 8 | pp2_sub_tlv_ssl -> length_lo ;
10551070 switch (pp2_sub_tlv_ssl -> type )
10561071 {
@@ -1090,12 +1105,12 @@ static int32_t pp2_parse_hdr(uint8_t *buffer, uint32_t buffer_length, pp_info_t
10901105 break ;
10911106 case PP2_TYPE_AWS :
10921107 {
1093- pp2_tlv_aws_t * pp2_tlv_aws ;
1108+ const pp2_tlv_aws_t * pp2_tlv_aws ;
10941109 if (pp2_tlv_len < sizeof (pp2_tlv_aws_t ))
10951110 {
10961111 return - ERR_PP2_TYPE_AWS ;
10971112 }
1098- pp2_tlv_aws = (pp2_tlv_aws_t * ) pp2_tlv -> value ;
1113+ pp2_tlv_aws = (const pp2_tlv_aws_t * ) pp2_tlv -> value ;
10991114 /* Connection is done through Private Link/Interface VPC endpoint */
11001115 if (pp2_tlv_aws -> type == PP2_SUBTYPE_AWS_VPCE_ID ) /* US-ASCII */
11011116 {
@@ -1109,12 +1124,12 @@ static int32_t pp2_parse_hdr(uint8_t *buffer, uint32_t buffer_length, pp_info_t
11091124 }
11101125 case PP2_TYPE_AZURE :
11111126 {
1112- pp2_tlv_azure_t * pp2_tlv_azure ;
1127+ const pp2_tlv_azure_t * pp2_tlv_azure ;
11131128 if (pp2_tlv_len < sizeof (pp2_tlv_azure_t ))
11141129 {
11151130 return - ERR_PP2_TYPE_AZURE ;
11161131 }
1117- pp2_tlv_azure = (pp2_tlv_azure_t * ) pp2_tlv -> value ;
1132+ pp2_tlv_azure = (const pp2_tlv_azure_t * ) pp2_tlv -> value ;
11181133 /* Connection is done through Private Link service */
11191134 if (pp2_tlv_azure -> type == PP2_SUBTYPE_AZURE_PRIVATEENDPOINT_LINKID ) /* 32-bit number */
11201135 {
@@ -1309,7 +1324,7 @@ static int32_t pp1_parse_hdr(const uint8_t *buffer, uint32_t buffer_length, pp_i
13091324 return pp1_hdr_len ;
13101325}
13111326
1312- int32_t pp_parse_hdr (uint8_t * buffer , uint32_t buffer_length , pp_info_t * pp_info )
1327+ int32_t pp_parse_hdr (const uint8_t * buffer , uint32_t buffer_length , pp_info_t * pp_info )
13131328{
13141329 memset (pp_info , 0 , sizeof (* pp_info ));
13151330 if (buffer_length >= 16 && !memcmp (buffer , PP2_SIG , 12 ))
0 commit comments