11#include <stdio.h>
22#include <stdlib.h>
3+ #include <string.h>
34#ifdef _WIN32
45 #include <ws2tcpip.h>
56 #pragma comment(lib, "ws2_32.lib")
1112
1213int main ()
1314{
14- // Create a v1 PROXY protocol header
15- pp_info_t pp_info_in = {
15+ /* Create a v1 PROXY protocol header */
16+ pp_info_t pp_info_in_v1 = {
17+ .address_family = ADDR_FAMILY_INET ,
18+ .transport_protocol = TRANSPORT_PROTOCOL_STREAM ,
1619 .src_addr = "172.22.32.1" ,
1720 .dst_addr = "172.22.33.1" ,
1821 .src_port = 4040 ,
1922 .dst_port = 443
2023 };
21- uint32_t pp1_hdr_len ;
24+ uint16_t pp1_hdr_len ;
2225 uint32_t error ;
23- uint8_t * pp1_hdr = pp_create_hdr (1 , AF_INET , & pp_info_in , & pp1_hdr_len , & error );
24- if (!pp1_hdr )
26+ uint8_t * pp1_hdr = pp_create_hdr (1 , & pp_info_in_v1 , & pp1_hdr_len , & error );
27+ /* Clear the pp_info passed in pp_create_hdr(). Not really needed for v1 but good to do out of principle */
28+ pp_info_clear (& pp_info_in_v1 );
29+ if (error != ERR_NULL )
2530 {
2631 fprintf (stderr , "pp_create_hdr() failed: %s" , pp_strerror (error ));
27- free (pp1_hdr );
2832 return EXIT_FAILURE ;
2933 }
3034
31- // Parse
35+ /* Parse a v1 PROXY protocol header */
3236 pp_info_t pp_info_out ;
3337 int32_t rc = pp_parse_hdr (pp1_hdr , pp1_hdr_len , & pp_info_out );
3438 free (pp1_hdr );
35- if (rc == 0 )
39+ if (! rc )
3640 {
3741 printf ("Not a PROXY protocol header\n" );
3842 }
@@ -49,34 +53,44 @@ int main()
4953 pp_info_out .src_addr , pp_info_out .dst_addr ,
5054 pp_info_out .src_port , pp_info_out .dst_port );
5155 }
56+ /* ALWAYS clear the pp_info after a call to pp_parse_hdr() */
5257 pp_info_clear (& pp_info_out );
5358
54- // Parse
55- uint8_t pp2_hdr_vpce [] = {
56- 0x0d , 0x0a , 0x0d , 0x0a , /* Start of v2 signature */
57- 0x00 , 0x0d , 0x0a , 0x51 ,
58- 0x55 , 0x49 , 0x54 , 0x0a , /* End of v2 signature */
59- 0x21 , 0x11 , 0x00 , 0x40 , /* ver_cmd, fam and len */
60- 0xc0 , 0xa8 , 0x0a , 0x64 , /* Source IP */
61- 0xc0 , 0xa8 , 0x0b , 0x5a , /* Destination IP */
62- 0xa5 , 0x5c , 0x1f , 0x90 , /* Source port, Destination port */
63- 0x03 , 0x00 , 0x04 , 0xe5 , /* CRC32C TLV start */
64- 0x18 , 0x86 , 0xf8 , 0xea , /* CRC32C TLV end, AWS VPCE ID TLV start */
65- 0x00 , 0x17 , 0x01 , 0x76 ,
66- 0x70 , 0x63 , 0x65 , 0x2d ,
67- 0x32 , 0x33 , 0x64 , 0x38 ,
68- 0x65 , 0x7a , 0x6a , 0x6b ,
69- 0x33 , 0x38 , 0x62 , 0x63 ,
70- 0x68 , 0x69 , 0x6c , 0x6d ,
71- 0x34 , 0x04 , 0x00 , 0x10 , /* AWS VPCE ID TLV end, NOOP TLV start */
72- 0x00 , 0x00 , 0x00 , 0x00 ,
73- 0x00 , 0x00 , 0x00 , 0x00 ,
74- 0x00 , 0x00 , 0x00 , 0x00 ,
75- 0x00 , 0x00 , 0x00 , 0x00 , /* NOOP TLV end */
59+ /* Create a v2 PROXY protocol header with some TLVs */
60+ pp_info_t pp_info_in_v2 = {
61+ .address_family = ADDR_FAMILY_INET ,
62+ .transport_protocol = TRANSPORT_PROTOCOL_STREAM ,
63+ .src_addr = "192.168.10.100" ,
64+ .dst_addr = "192.168.11.90" ,
65+ .src_port = 42332 ,
66+ .dst_port = 8080 ,
67+ .pp2_info = {
68+ .crc32c = 1 , /* Add crc32c checksum */
69+ .pp2_ssl_info = { /* Add SSL information */
70+ .ssl = 1 ,
71+ .cert_in_connection = 1 ,
72+ .cert_in_session = 1 ,
73+ .cert_verified = 1 ,
74+ }
75+ }
7676 };
77+ /* Add SSL TLVs */
78+ pp_info_add_ssl (& pp_info_in_v2 , "TLSv1.2" , "ECDHE-RSA-AES128-GCM-SHA256" , "SHA256" , "RSA2048" , "example.com" , 11 );
79+ /* Add Azure Link ID TLV */
80+ pp_info_add_azure_linkid (& pp_info_in_v2 , 1234 );
81+ uint8_t * pp2_hdr = pp_create_hdr (2 , & pp_info_in_v2 , & pp1_hdr_len , & error );
82+ /* IMPORTANT: Clear the pp_info passed in pp_create_hdr() because TLVs were created. Otherwise memory will be leaked */
83+ pp_info_clear (& pp_info_in_v2 );
84+ if (error != ERR_NULL )
85+ {
86+ fprintf (stderr , "pp_create_hdr() failed: %s" , pp_strerror (error ));
87+ return EXIT_FAILURE ;
88+ }
7789
78- rc = pp_parse_hdr (pp2_hdr_vpce , sizeof (pp2_hdr_vpce ), & pp_info_out );
79- if (rc == 0 )
90+ /* Parse a v2 PROXY protocol header */
91+ rc = pp_parse_hdr (pp2_hdr , pp1_hdr_len , & pp_info_out );
92+ free (pp2_hdr );
93+ if (!rc )
8094 {
8195 printf ("Not a PROXY protocol header\n" );
8296 }
@@ -88,13 +102,31 @@ int main()
88102 }
89103 else
90104 {
91- uint16_t tlv_value_len ;
92- char * vpc_id = pp_info_get_tlv_value (& pp_info_out , PP2_TYPE_AWS , PP2_SUBTYPE_AWS_VPCE_ID , & tlv_value_len );
93- printf ("%d bytes PROXY protocol header: AWS VPC ID: %s. %s %s %hu %hu\n" ,
94- rc , vpc_id ,
105+ uint16_t length , cn_length ;
106+ const uint8_t * azure_linkid = pp_info_get_azure_linkid (& pp_info_out , & length );
107+ uint32_t linkid ;
108+ memcpy (& linkid , azure_linkid , length );
109+ const uint8_t * cn = pp_info_get_ssl_cn (& pp_info_out , & cn_length );
110+ printf ("%d bytes PROXY protocol header:\n"
111+ "\tAzure Link ID: %u\n"
112+ "\tCRC32C checksum: %s\n"
113+ "\tSSL version: %s\n"
114+ "\tSSL cipher: %s\n"
115+ "\tSSL sig_alg: %s\n"
116+ "\tSSL key_alg: %s\n"
117+ "\tSSL CN: %.*s\n"
118+ "%s %s %hu %hu\n" ,
119+ rc , linkid ,
120+ pp_info_out .pp2_info .crc32c == 1 ? "verified" : "not present" ,
121+ pp_info_get_ssl_version (& pp_info_out , & length ),
122+ pp_info_get_ssl_cipher (& pp_info_out , & length ),
123+ pp_info_get_ssl_sig_alg (& pp_info_out , & length ),
124+ pp_info_get_ssl_key_alg (& pp_info_out , & length ),
125+ cn_length , cn ,
95126 pp_info_out .src_addr , pp_info_out .dst_addr ,
96127 pp_info_out .src_port , pp_info_out .dst_port );
97128 }
129+ /* ALWAYS clear the pp_info after a call to pp_parse_hdr() */
98130 pp_info_clear (& pp_info_out );
99131
100132 return EXIT_SUCCESS ;
0 commit comments