Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion proxy-protocol.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Revision history
reserved TLV type ranges, added TLV documentation, clarified
string encoding. With contributions from Andriy Palamarchuk
(Amazon.com).
2020/03/05 - added the unique ID TLV type (Tim Düsterhus)
2020/03/05 - added the unique ID TLV type (Tim Düsterhus)


1. Background
Expand Down
57 changes: 41 additions & 16 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ pub enum EncodeError {
/// An error occurred while encoding version 1.
#[snafu(display("there was an error while encoding the v1 header: {}", source))]
WriteVersion1 { source: version1::EncodeError },
/// An error occurred while encoding version 2.
#[snafu(display("there was an error while encoding the v2 header: {}", source))]
WriteVersion2 { source: version2::EncodeError },
}

/// The PROXY header emitted at most once at the start of a new connection.
Expand Down Expand Up @@ -70,6 +73,7 @@ pub enum ProxyHeader {

/// The addresses used to connect to the proxy.
addresses: version2::ProxyAddresses,
extensions: Vec<version2::ExtensionTlv>,
},
}

Expand Down Expand Up @@ -150,7 +154,9 @@ pub fn encode(header: ProxyHeader) -> Result<BytesMut, EncodeError> {
command,
transport_protocol,
addresses,
} => version2::encode(command, transport_protocol, addresses),
extensions,
} => version2::encode(command, transport_protocol, addresses, &extensions[..])
.context(WriteVersion2)?,

#[allow(unreachable_patterns)] // May be required to be exhaustive.
_ => unimplemented!("Unimplemented version?"),
Expand Down Expand Up @@ -191,15 +197,15 @@ mod parse_tests {
assert!(!buf.has_remaining()); // Consume the ENTIRE header!

fn valid_v4(
(a, b, c, d): (u8, u8, u8, u8),
e: u16,
(f, g, h, i): (u8, u8, u8, u8),
j: u16,
(s0, s1, s2, s3): (u8, u8, u8, u8),
sp: u16,
(d0, d1, d2, d3): (u8, u8, u8, u8),
dp: u16,
) -> ProxyHeader {
ProxyHeader::Version1 {
addresses: version1::ProxyAddresses::Ipv4 {
source: SocketAddrV4::new(Ipv4Addr::new(a, b, c, d), e),
destination: SocketAddrV4::new(Ipv4Addr::new(f, g, h, i), j),
source: SocketAddrV4::new(Ipv4Addr::new(s0, s1, s2, s3), sp),
destination: SocketAddrV4::new(Ipv4Addr::new(d0, d1, d2, d3), dp),
},
}
}
Expand All @@ -223,15 +229,25 @@ mod parse_tests {
);

fn valid_v6(
(a, b, c, d, e, f, g, h): (u16, u16, u16, u16, u16, u16, u16, u16),
i: u16,
(j, k, l, m, n, o, p, q): (u16, u16, u16, u16, u16, u16, u16, u16),
r: u16,
(s0, s1, s2, s3, s4, s5, s6, s7): (u16, u16, u16, u16, u16, u16, u16, u16),
sp: u16,
(d0, d1, d2, d3, d4, d5, d6, d7): (u16, u16, u16, u16, u16, u16, u16, u16),
dp: u16,
) -> ProxyHeader {
ProxyHeader::Version1 {
addresses: version1::ProxyAddresses::Ipv6 {
source: SocketAddrV6::new(Ipv6Addr::new(a, b, c, d, e, f, g, h), i, 0, 0),
destination: SocketAddrV6::new(Ipv6Addr::new(j, k, l, m, n, o, p, q), r, 0, 0),
source: SocketAddrV6::new(
Ipv6Addr::new(s0, s1, s2, s3, s4, s5, s6, s7),
sp,
0,
0,
),
destination: SocketAddrV6::new(
Ipv6Addr::new(d0, d1, d2, d3, d4, d5, d6, d7),
dp,
0,
0,
),
},
}
}
Expand Down Expand Up @@ -313,7 +329,7 @@ mod parse_tests {
0x49,
0x54,
0x0A,
(2 << 4) | 0,
2 << 4,
];
const PREFIX_PROXY: [u8; 13] = [
0x0D,
Expand All @@ -337,6 +353,7 @@ mod parse_tests {
command: version2::ProxyCommand::Local,
addresses: version2::ProxyAddresses::Unspec,
transport_protocol: version2::ProxyTransportProtocol::Unspec,
extensions: Vec::new(),
}),
);
assert_eq!(
Expand All @@ -345,6 +362,7 @@ mod parse_tests {
command: version2::ProxyCommand::Proxy,
addresses: version2::ProxyAddresses::Unspec,
transport_protocol: version2::ProxyTransportProtocol::Unspec,
extensions: Vec::new(),
}),
);

Expand Down Expand Up @@ -378,7 +396,7 @@ mod parse_tests {
1,
1,
// TLV
69,
version2::PP2_TYPE_NOOP,
0,
0,
][..]
Expand All @@ -393,6 +411,7 @@ mod parse_tests {
source: SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 65535),
destination: SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 257),
},
extensions: Vec::new(),
})
);

Expand Down Expand Up @@ -439,6 +458,7 @@ mod parse_tests {
source: SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 0),
destination: SocketAddrV4::new(Ipv4Addr::new(255, 255, 255, 255), 255 << 8),
},
extensions: Vec::new(),
})
);
assert!(data.remaining() == 4); // Consume the entire header
Expand Down Expand Up @@ -497,7 +517,7 @@ mod parse_tests {
1,
1,
// TLV
69,
version2::PP2_TYPE_NOOP,
0,
0,
][..],
Expand All @@ -522,6 +542,7 @@ mod parse_tests {
0,
)
},
extensions: Vec::new(),
})
);

Expand Down Expand Up @@ -602,6 +623,7 @@ mod parse_tests {
0,
),
},
extensions: Vec::new(),
})
);
assert!(data.remaining() == 4); // Consume the entire header
Expand Down Expand Up @@ -629,6 +651,9 @@ mod parse_tests {
// 3 bytes is clearly too few if we expect 2 IPv4s and ports
0,
3,
0,
0,
0,
][..],
]
.concat()
Expand Down
38 changes: 23 additions & 15 deletions src/version1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,7 @@ pub(crate) fn parse(buf: &mut impl Buf) -> Result<super::ProxyHeader, ParseError
_ => unreachable!(),
};

Ok(super::ProxyHeader::Version1 {
addresses,
})
Ok(super::ProxyHeader::Version1 { addresses })
}

pub(crate) fn encode(addresses: ProxyAddresses) -> Result<BytesMut, EncodeError> {
Expand Down Expand Up @@ -278,15 +276,15 @@ mod parse_tests {
#[test]
fn test_valid_ipv4_cases() {
fn valid(
(a, b, c, d): (u8, u8, u8, u8),
e: u16,
(f, g, h, i): (u8, u8, u8, u8),
j: u16,
(s0, s1, s2, s3): (u8, u8, u8, u8),
sp: u16,
(d0, d1, d2, d3): (u8, u8, u8, u8),
dp: u16,
) -> ProxyHeader {
ProxyHeader::Version1 {
addresses: ProxyAddresses::Ipv4 {
source: SocketAddrV4::new(Ipv4Addr::new(a, b, c, d), e),
destination: SocketAddrV4::new(Ipv4Addr::new(f, g, h, i), j),
source: SocketAddrV4::new(Ipv4Addr::new(s0, s1, s2, s3), sp),
destination: SocketAddrV4::new(Ipv4Addr::new(d0, d1, d2, d3), dp),
},
}
}
Expand All @@ -312,15 +310,25 @@ mod parse_tests {
#[test]
fn test_valid_ipv6_cases() {
fn valid(
(a, b, c, d, e, f, g, h): (u16, u16, u16, u16, u16, u16, u16, u16),
i: u16,
(j, k, l, m, n, o, p, q): (u16, u16, u16, u16, u16, u16, u16, u16),
r: u16,
(s0, s1, s2, s3, s4, s5, s6, s7): (u16, u16, u16, u16, u16, u16, u16, u16),
sp: u16,
(d0, d1, d2, d3, d4, d5, d6, d7): (u16, u16, u16, u16, u16, u16, u16, u16),
dp: u16,
) -> ProxyHeader {
ProxyHeader::Version1 {
addresses: ProxyAddresses::Ipv6 {
source: SocketAddrV6::new(Ipv6Addr::new(a, b, c, d, e, f, g, h), i, 0, 0),
destination: SocketAddrV6::new(Ipv6Addr::new(j, k, l, m, n, o, p, q), r, 0, 0),
source: SocketAddrV6::new(
Ipv6Addr::new(s0, s1, s2, s3, s4, s5, s6, s7),
sp,
0,
0,
),
destination: SocketAddrV6::new(
Ipv6Addr::new(d0, d1, d2, d3, d4, d5, d6, d7),
dp,
0,
0,
),
},
}
}
Expand Down
Loading