Skip to content

Commit 9e1c2e1

Browse files
Merge pull request #11 from kosmas-valianos/AddTLVsInCreation
Add support for adding TLVs when creating v2 PROXY protocol headers
2 parents 422166e + 4797b62 commit 9e1c2e1

4 files changed

Lines changed: 665 additions & 325 deletions

File tree

examples/client_server.c

Lines changed: 68 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
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")
@@ -11,28 +12,31 @@
1112

1213
int 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

Comments
 (0)