/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ppp-2.3.0/src/v2/mod.rs
Line | Count | Source |
1 | | //! Version 2 of the HAProxy protocol (binary version). |
2 | | //! |
3 | | //! See <https://haproxy.org/download/1.8/doc/proxy-protocol.txt> |
4 | | |
5 | | mod builder; |
6 | | mod error; |
7 | | mod model; |
8 | | |
9 | | pub use crate::ip::{IPv4, IPv6}; |
10 | | pub use builder::{Builder, WriteToHeader, Writer}; |
11 | | pub use error::ParseError; |
12 | | pub use model::{ |
13 | | AddressFamily, Addresses, Command, Header, Protocol, Type, TypeLengthValue, TypeLengthValues, |
14 | | Unix, Version, PROTOCOL_PREFIX, |
15 | | }; |
16 | | use model::{MINIMUM_LENGTH, MINIMUM_TLV_LENGTH}; |
17 | | use std::borrow::Cow; |
18 | | use std::net::{Ipv4Addr, Ipv6Addr}; |
19 | | |
20 | | /// Masks the right 4-bits so only the left 4-bits are present. |
21 | | const LEFT_MASK: u8 = 0xF0; |
22 | | /// Masks the left 4-bits so only the right 4-bits are present. |
23 | | const RIGHT_MASK: u8 = 0x0F; |
24 | | /// The index of the version-command byte. |
25 | | const VERSION_COMMAND: usize = PROTOCOL_PREFIX.len(); |
26 | | /// The index of the address family-protocol byte. |
27 | | const ADDRESS_FAMILY_PROTOCOL: usize = VERSION_COMMAND + 1; |
28 | | /// The index of the start of the big-endian u16 length. |
29 | | const LENGTH: usize = ADDRESS_FAMILY_PROTOCOL + 1; |
30 | | |
31 | | /// Parses the addresses from the header payload. |
32 | 0 | fn parse_addresses(address_family: AddressFamily, bytes: &[u8]) -> Addresses { |
33 | 0 | match address_family { |
34 | 0 | AddressFamily::Unspecified => Addresses::Unspecified, |
35 | | AddressFamily::IPv4 => { |
36 | 0 | let source_address = Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3]); |
37 | 0 | let destination_address = Ipv4Addr::new(bytes[4], bytes[5], bytes[6], bytes[7]); |
38 | 0 | let source_port = u16::from_be_bytes([bytes[8], bytes[9]]); |
39 | 0 | let destination_port = u16::from_be_bytes([bytes[10], bytes[11]]); |
40 | | |
41 | 0 | Addresses::IPv4(IPv4 { |
42 | 0 | source_address, |
43 | 0 | destination_address, |
44 | 0 | source_port, |
45 | 0 | destination_port, |
46 | 0 | }) |
47 | | } |
48 | | AddressFamily::IPv6 => { |
49 | 0 | let mut address = [0; 16]; |
50 | | |
51 | 0 | address[..].copy_from_slice(&bytes[..16]); |
52 | 0 | let source_address = Ipv6Addr::from(address); |
53 | | |
54 | 0 | address[..].copy_from_slice(&bytes[16..32]); |
55 | 0 | let destination_address = Ipv6Addr::from(address); |
56 | | |
57 | 0 | let source_port = u16::from_be_bytes([bytes[32], bytes[33]]); |
58 | 0 | let destination_port = u16::from_be_bytes([bytes[34], bytes[35]]); |
59 | | |
60 | 0 | Addresses::IPv6(IPv6 { |
61 | 0 | source_address, |
62 | 0 | destination_address, |
63 | 0 | source_port, |
64 | 0 | destination_port, |
65 | 0 | }) |
66 | | } |
67 | | AddressFamily::Unix => { |
68 | 0 | let mut source = [0; 108]; |
69 | 0 | let mut destination = [0; 108]; |
70 | | |
71 | 0 | source[..].copy_from_slice(&bytes[..108]); |
72 | 0 | destination[..].copy_from_slice(&bytes[108..]); |
73 | | |
74 | 0 | Addresses::Unix(Unix { |
75 | 0 | source, |
76 | 0 | destination, |
77 | 0 | }) |
78 | | } |
79 | | } |
80 | 0 | } |
81 | | |
82 | | impl<'a> TryFrom<&'a [u8]> for Header<'a> { |
83 | | type Error = ParseError; |
84 | | |
85 | 0 | fn try_from(input: &'a [u8]) -> Result<Self, Self::Error> { |
86 | 0 | if input.len() < PROTOCOL_PREFIX.len() { |
87 | 0 | if PROTOCOL_PREFIX.starts_with(input) { |
88 | 0 | return Err(ParseError::Incomplete(input.len())); |
89 | | } else { |
90 | 0 | return Err(ParseError::Prefix); |
91 | | } |
92 | 0 | } |
93 | | |
94 | 0 | if &input[..VERSION_COMMAND] != PROTOCOL_PREFIX { |
95 | 0 | return Err(ParseError::Prefix); |
96 | 0 | } |
97 | | |
98 | 0 | if input.len() < MINIMUM_LENGTH { |
99 | 0 | return Err(ParseError::Incomplete(input.len())); |
100 | 0 | } |
101 | | |
102 | 0 | let version = match input[VERSION_COMMAND] & LEFT_MASK { |
103 | 0 | 0x20 => Version::Two, |
104 | 0 | v => return Err(ParseError::Version(v)), |
105 | | }; |
106 | 0 | let command = match input[VERSION_COMMAND] & RIGHT_MASK { |
107 | 0 | 0x00 => Command::Local, |
108 | 0 | 0x01 => Command::Proxy, |
109 | 0 | c => return Err(ParseError::Command(c)), |
110 | | }; |
111 | | |
112 | 0 | let address_family = match input[ADDRESS_FAMILY_PROTOCOL] & LEFT_MASK { |
113 | 0 | 0x00 => AddressFamily::Unspecified, |
114 | 0 | 0x10 => AddressFamily::IPv4, |
115 | 0 | 0x20 => AddressFamily::IPv6, |
116 | 0 | 0x30 => AddressFamily::Unix, |
117 | 0 | a => return Err(ParseError::AddressFamily(a)), |
118 | | }; |
119 | 0 | let protocol = match input[ADDRESS_FAMILY_PROTOCOL] & RIGHT_MASK { |
120 | 0 | 0x00 => Protocol::Unspecified, |
121 | 0 | 0x01 => Protocol::Stream, |
122 | 0 | 0x02 => Protocol::Datagram, |
123 | 0 | p => return Err(ParseError::Protocol(p)), |
124 | | }; |
125 | | |
126 | 0 | let length = u16::from_be_bytes([input[LENGTH], input[LENGTH + 1]]) as usize; |
127 | 0 | let address_family_bytes = address_family.byte_length().unwrap_or_default(); |
128 | | |
129 | 0 | if length < address_family_bytes { |
130 | 0 | return Err(ParseError::InvalidAddresses(length, address_family_bytes)); |
131 | 0 | } |
132 | | |
133 | 0 | let full_length = MINIMUM_LENGTH + length; |
134 | | |
135 | 0 | if input.len() < full_length { |
136 | 0 | return Err(ParseError::Partial(input.len() - MINIMUM_LENGTH, length)); |
137 | 0 | } |
138 | | |
139 | 0 | let header = &input[..full_length]; |
140 | 0 | let addresses = parse_addresses( |
141 | 0 | address_family, |
142 | 0 | &header[MINIMUM_LENGTH..MINIMUM_LENGTH + address_family_bytes], |
143 | | ); |
144 | | |
145 | 0 | Ok(Header { |
146 | 0 | header: Cow::Borrowed(header), |
147 | 0 | version, |
148 | 0 | command, |
149 | 0 | protocol, |
150 | 0 | addresses, |
151 | 0 | }) |
152 | 0 | } |
153 | | } |
154 | | |
155 | | #[cfg(test)] |
156 | | mod tests { |
157 | | use super::*; |
158 | | use model::{Type, TypeLengthValue}; |
159 | | |
160 | | #[test] |
161 | | fn no_tlvs() { |
162 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
163 | | |
164 | | input.extend_from_slice(PROTOCOL_PREFIX); |
165 | | input.push(0x21); |
166 | | input.push(0x11); |
167 | | input.extend([0, 12]); |
168 | | input.extend([127, 0, 0, 1]); |
169 | | input.extend([127, 0, 0, 2]); |
170 | | input.extend([0, 80]); |
171 | | input.extend([1, 187]); |
172 | | |
173 | | let expected = Header { |
174 | | header: Cow::Borrowed(input.as_slice()), |
175 | | version: Version::Two, |
176 | | command: Command::Proxy, |
177 | | protocol: Protocol::Stream, |
178 | | addresses: IPv4::new([127, 0, 0, 1], [127, 0, 0, 2], 80, 443).into(), |
179 | | }; |
180 | | let actual = Header::try_from(input.as_slice()).unwrap(); |
181 | | |
182 | | assert_eq!(actual, expected); |
183 | | assert!(actual.tlvs().next().is_none()); |
184 | | assert_eq!(actual.length(), 12); |
185 | | assert_eq!(actual.address_family(), AddressFamily::IPv4); |
186 | | assert_eq!( |
187 | | actual.address_bytes(), |
188 | | &[127, 0, 0, 1, 127, 0, 0, 2, 0, 80, 1, 187] |
189 | | ); |
190 | | assert_eq!(actual.tlv_bytes(), &[]); |
191 | | assert_eq!(actual.as_bytes(), input.as_slice()); |
192 | | } |
193 | | |
194 | | #[test] |
195 | | fn no_tlvs_unspec() { |
196 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
197 | | |
198 | | input.extend_from_slice(PROTOCOL_PREFIX); |
199 | | input.push(0x21); |
200 | | input.push(0x00); |
201 | | input.extend([0, 12]); |
202 | | input.extend([127, 0, 0, 1]); |
203 | | input.extend([127, 0, 0, 2]); |
204 | | input.extend([0, 80]); |
205 | | input.extend([1, 187]); |
206 | | |
207 | | let expected = Header { |
208 | | header: input.as_slice().into(), |
209 | | version: Version::Two, |
210 | | command: Command::Proxy, |
211 | | protocol: Protocol::Unspecified, |
212 | | addresses: Addresses::Unspecified, |
213 | | }; |
214 | | let actual = Header::try_from(input.as_slice()).unwrap(); |
215 | | |
216 | | assert_eq!(actual, expected); |
217 | | assert!(actual.tlvs().next().is_none()); |
218 | | assert_eq!(actual.length(), 12); |
219 | | assert_eq!(actual.address_family(), AddressFamily::Unspecified); |
220 | | assert_eq!( |
221 | | actual.address_bytes(), |
222 | | &[127, 0, 0, 1, 127, 0, 0, 2, 0, 80, 1, 187] |
223 | | ); |
224 | | assert_eq!(actual.tlv_bytes(), &[]); |
225 | | assert_eq!(actual.as_bytes(), input.as_slice()); |
226 | | } |
227 | | |
228 | | #[test] |
229 | | fn no_tlvs_unspec_stream() { |
230 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
231 | | |
232 | | input.extend_from_slice(PROTOCOL_PREFIX); |
233 | | input.push(0x21); |
234 | | input.push(0x01); |
235 | | input.extend([0, 8]); |
236 | | input.extend([127, 0, 0, 1]); |
237 | | input.extend([127, 0, 0, 2]); |
238 | | |
239 | | let expected = Header { |
240 | | header: Cow::Borrowed(input.as_slice()), |
241 | | version: Version::Two, |
242 | | command: Command::Proxy, |
243 | | protocol: Protocol::Stream, |
244 | | addresses: Addresses::Unspecified, |
245 | | }; |
246 | | let actual = Header::try_from(input.as_slice()).unwrap(); |
247 | | |
248 | | assert_eq!(actual, expected); |
249 | | assert!(actual.tlvs().next().is_none()); |
250 | | assert_eq!(actual.length(), 8); |
251 | | assert_eq!(actual.address_family(), AddressFamily::Unspecified); |
252 | | assert_eq!(actual.address_bytes(), &[127, 0, 0, 1, 127, 0, 0, 2]); |
253 | | assert_eq!(actual.tlv_bytes(), &[]); |
254 | | assert_eq!(actual.as_bytes(), input.as_slice()); |
255 | | } |
256 | | |
257 | | #[test] |
258 | | fn no_tlvs_unspec_ipv4() { |
259 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
260 | | |
261 | | input.extend_from_slice(PROTOCOL_PREFIX); |
262 | | input.push(0x21); |
263 | | input.push(0x10); |
264 | | input.extend([0, 8]); |
265 | | input.extend([127, 0, 0, 1]); |
266 | | input.extend([127, 0, 0, 2]); |
267 | | |
268 | | let actual = Header::try_from(input.as_slice()).unwrap_err(); |
269 | | |
270 | | assert_eq!(actual, ParseError::InvalidAddresses(8, 12)); |
271 | | } |
272 | | |
273 | | #[test] |
274 | | fn invalid_version() { |
275 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
276 | | |
277 | | input.extend_from_slice(PROTOCOL_PREFIX); |
278 | | input.push(0x11); |
279 | | input.push(0x11); |
280 | | input.extend([0, 12]); |
281 | | input.extend([127, 0, 0, 1]); |
282 | | input.extend([127, 0, 0, 2]); |
283 | | input.extend([0, 80]); |
284 | | input.extend([1, 187]); |
285 | | |
286 | | let actual = Header::try_from(input.as_slice()).unwrap_err(); |
287 | | |
288 | | assert_eq!(actual, ParseError::Version(0x10)); |
289 | | } |
290 | | |
291 | | #[test] |
292 | | fn invalid_address_family() { |
293 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
294 | | |
295 | | input.extend_from_slice(PROTOCOL_PREFIX); |
296 | | input.push(0x21); |
297 | | input.push(0x51); |
298 | | input.extend([0, 12]); |
299 | | input.extend([127, 0, 0, 1]); |
300 | | input.extend([127, 0, 0, 2]); |
301 | | input.extend([0, 80]); |
302 | | input.extend([1, 187]); |
303 | | |
304 | | let actual = Header::try_from(input.as_slice()).unwrap_err(); |
305 | | |
306 | | assert_eq!(actual, ParseError::AddressFamily(0x50)); |
307 | | } |
308 | | |
309 | | #[test] |
310 | | fn invalid_command() { |
311 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
312 | | |
313 | | input.extend_from_slice(PROTOCOL_PREFIX); |
314 | | input.push(0x23); |
315 | | input.push(0x11); |
316 | | input.extend([0, 12]); |
317 | | input.extend([127, 0, 0, 1]); |
318 | | input.extend([127, 0, 0, 2]); |
319 | | input.extend([0, 80]); |
320 | | input.extend([1, 187]); |
321 | | |
322 | | let actual = Header::try_from(input.as_slice()).unwrap_err(); |
323 | | |
324 | | assert_eq!(actual, ParseError::Command(0x03)); |
325 | | } |
326 | | |
327 | | #[test] |
328 | | fn invalid_protocol() { |
329 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
330 | | |
331 | | input.extend_from_slice(PROTOCOL_PREFIX); |
332 | | input.push(0x20); |
333 | | input.push(0x17); |
334 | | input.extend([0, 12]); |
335 | | input.extend([127, 0, 0, 1]); |
336 | | input.extend([127, 0, 0, 2]); |
337 | | input.extend([0, 80]); |
338 | | input.extend([1, 187]); |
339 | | |
340 | | let actual = Header::try_from(input.as_slice()).unwrap_err(); |
341 | | |
342 | | assert_eq!(actual, ParseError::Protocol(0x07)); |
343 | | } |
344 | | |
345 | | #[test] |
346 | | fn proxy_with_extra() { |
347 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
348 | | |
349 | | input.extend_from_slice(PROTOCOL_PREFIX); |
350 | | input.push(0x21); |
351 | | input.push(0x11); |
352 | | input.extend([0, 12]); |
353 | | input.extend([127, 0, 0, 1]); |
354 | | input.extend([127, 0, 0, 2]); |
355 | | input.extend([0, 80]); |
356 | | input.extend([1, 187]); |
357 | | input.extend([42]); |
358 | | |
359 | | let header = &input[..input.len() - 1]; |
360 | | let expected = Header { |
361 | | header: header.into(), |
362 | | version: Version::Two, |
363 | | command: Command::Proxy, |
364 | | protocol: Protocol::Stream, |
365 | | addresses: IPv4::new([127, 0, 0, 1], [127, 0, 0, 2], 80, 443).into(), |
366 | | }; |
367 | | let actual = Header::try_from(input.as_slice()).unwrap(); |
368 | | |
369 | | assert_eq!(actual, expected); |
370 | | assert!(actual.tlvs().next().is_none()); |
371 | | assert_eq!(actual.length(), 12); |
372 | | assert_eq!(actual.address_family(), AddressFamily::IPv4); |
373 | | assert_eq!( |
374 | | actual.address_bytes(), |
375 | | &[127, 0, 0, 1, 127, 0, 0, 2, 0, 80, 1, 187] |
376 | | ); |
377 | | assert_eq!(actual.tlv_bytes(), &[]); |
378 | | assert_eq!(actual.as_bytes(), header); |
379 | | } |
380 | | |
381 | | #[test] |
382 | | fn with_tlvs() { |
383 | | let source_address = [ |
384 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
385 | | 0xFF, 0xF2, |
386 | | ]; |
387 | | let destination_address = [ |
388 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
389 | | 0xFF, 0xF1, |
390 | | ]; |
391 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
392 | | |
393 | | input.extend_from_slice(PROTOCOL_PREFIX); |
394 | | input.push(0x21); |
395 | | input.push(0x21); |
396 | | input.extend([0, 45]); |
397 | | input.extend(source_address); |
398 | | input.extend(destination_address); |
399 | | input.extend([0, 80]); |
400 | | input.extend([1, 187]); |
401 | | input.extend([1, 0, 1, 5]); |
402 | | input.extend([3, 0, 2, 5, 5]); |
403 | | |
404 | | let expected = Header { |
405 | | header: input.as_slice().into(), |
406 | | version: Version::Two, |
407 | | command: Command::Proxy, |
408 | | protocol: Protocol::Stream, |
409 | | addresses: IPv6::new(source_address, destination_address, 80, 443).into(), |
410 | | }; |
411 | | let expected_tlvs = vec![ |
412 | | Ok(TypeLengthValue::new(Type::ALPN, &[5])), |
413 | | Ok(TypeLengthValue::new(Type::CRC32C, &[5, 5])), |
414 | | ]; |
415 | | |
416 | | let actual = Header::try_from(input.as_slice()).unwrap(); |
417 | | let actual_tlvs: Vec<Result<TypeLengthValue<'_>, ParseError>> = actual.tlvs().collect(); |
418 | | |
419 | | assert_eq!(actual, expected); |
420 | | assert_eq!(actual_tlvs, expected_tlvs); |
421 | | assert_eq!(actual.length(), 45); |
422 | | assert_eq!(actual.address_family(), AddressFamily::IPv6); |
423 | | assert_eq!( |
424 | | actual.address_bytes(), |
425 | | &[ |
426 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
427 | | 0xFF, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
428 | | 0xFF, 0xFF, 0xFF, 0xF1, 0, 80, 1, 187 |
429 | | ] |
430 | | ); |
431 | | assert_eq!(actual.tlv_bytes(), &[1, 0, 1, 5, 3, 0, 2, 5, 5]); |
432 | | assert_eq!(actual.as_bytes(), input.as_slice()); |
433 | | } |
434 | | |
435 | | #[test] |
436 | | fn tlvs_with_extra() { |
437 | | let source_address = [ |
438 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
439 | | 0xFF, 0xFF, |
440 | | ]; |
441 | | let destination_address = [ |
442 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
443 | | 0xFF, 0xF1, |
444 | | ]; |
445 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
446 | | |
447 | | input.extend_from_slice(PROTOCOL_PREFIX); |
448 | | input.push(0x21); |
449 | | input.push(0x21); |
450 | | input.extend([0, 45]); |
451 | | input.extend(source_address); |
452 | | input.extend(destination_address); |
453 | | input.extend([0, 80]); |
454 | | input.extend([1, 187]); |
455 | | input.extend([1, 0, 1, 5]); |
456 | | input.extend([4, 0, 2, 5, 5]); |
457 | | input.extend([2, 0, 2, 5, 5]); |
458 | | |
459 | | let header = &input[..input.len() - 5]; |
460 | | let expected = Header { |
461 | | header: header.into(), |
462 | | version: Version::Two, |
463 | | command: Command::Proxy, |
464 | | protocol: Protocol::Stream, |
465 | | addresses: IPv6::new(source_address, destination_address, 80, 443).into(), |
466 | | }; |
467 | | let expected_tlvs = vec![ |
468 | | Ok(TypeLengthValue::new(Type::ALPN, &[5])), |
469 | | Ok(TypeLengthValue::new(Type::NoOp, &[5, 5])), |
470 | | ]; |
471 | | |
472 | | let actual = Header::try_from(input.as_slice()).unwrap(); |
473 | | let actual_tlvs: Vec<Result<TypeLengthValue<'_>, ParseError>> = actual.tlvs().collect(); |
474 | | |
475 | | assert_eq!(actual, expected); |
476 | | assert_eq!(actual_tlvs, expected_tlvs); |
477 | | assert_eq!(actual.length(), 45); |
478 | | assert_eq!(actual.address_family(), AddressFamily::IPv6); |
479 | | assert_eq!( |
480 | | actual.address_bytes(), |
481 | | &[ |
482 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
483 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
484 | | 0xFF, 0xFF, 0xFF, 0xF1, 0, 80, 1, 187 |
485 | | ] |
486 | | ); |
487 | | assert_eq!(actual.tlv_bytes(), &[1, 0, 1, 5, 4, 0, 2, 5, 5]); |
488 | | assert_eq!(actual.as_bytes(), header); |
489 | | } |
490 | | |
491 | | #[test] |
492 | | fn unix_tlvs_with_extra() { |
493 | | let source_address = [0xFFu8; 108]; |
494 | | let destination_address = [0xAAu8; 108]; |
495 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
496 | | |
497 | | input.extend_from_slice(PROTOCOL_PREFIX); |
498 | | input.push(0x21); |
499 | | input.push(0x30); |
500 | | input.extend([0, 225]); |
501 | | input.extend(source_address); |
502 | | input.extend(destination_address); |
503 | | input.extend([2, 0, 2, 5, 5]); |
504 | | input.extend([48, 0, 1, 5]); |
505 | | input.extend([1, 0, 2, 5, 5]); |
506 | | |
507 | | let header = &input[..input.len() - 5]; |
508 | | let expected = Header { |
509 | | header: header.into(), |
510 | | version: Version::Two, |
511 | | command: Command::Proxy, |
512 | | protocol: Protocol::Unspecified, |
513 | | addresses: Unix::new(source_address, destination_address).into(), |
514 | | }; |
515 | | let mut expected_address_bytes = |
516 | | Vec::with_capacity(source_address.len() + destination_address.len()); |
517 | | expected_address_bytes.extend(source_address); |
518 | | expected_address_bytes.extend(destination_address); |
519 | | |
520 | | let expected_tlvs = vec![ |
521 | | Ok(TypeLengthValue::new(Type::Authority, &[5, 5])), |
522 | | Ok(TypeLengthValue::new(Type::NetworkNamespace, &[5])), |
523 | | ]; |
524 | | |
525 | | let actual = Header::try_from(input.as_slice()).unwrap(); |
526 | | let actual_tlvs: Vec<Result<TypeLengthValue<'_>, ParseError>> = actual.tlvs().collect(); |
527 | | |
528 | | assert_eq!(actual, expected); |
529 | | assert_eq!(actual_tlvs, expected_tlvs); |
530 | | assert_eq!(actual.length(), 225); |
531 | | assert_eq!(actual.address_family(), AddressFamily::Unix); |
532 | | assert_eq!(actual.address_bytes(), expected_address_bytes.as_slice()); |
533 | | assert_eq!(actual.tlv_bytes(), &[2, 0, 2, 5, 5, 48, 0, 1, 5]); |
534 | | assert_eq!(actual.as_bytes(), header); |
535 | | } |
536 | | |
537 | | #[test] |
538 | | fn with_tlvs_without_ports() { |
539 | | let source_address = [ |
540 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
541 | | 0xFF, 0xFF, |
542 | | ]; |
543 | | let destination_address = [ |
544 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
545 | | 0xFF, 0xF1, |
546 | | ]; |
547 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
548 | | |
549 | | input.extend_from_slice(PROTOCOL_PREFIX); |
550 | | input.push(0x21); |
551 | | input.push(0x20); |
552 | | input.extend([0, 41]); |
553 | | input.extend(source_address); |
554 | | input.extend(destination_address); |
555 | | input.extend([1, 0, 1, 5]); |
556 | | input.extend([3, 0, 2, 5, 5]); |
557 | | |
558 | | let expected = Header { |
559 | | header: input.as_slice().into(), |
560 | | version: Version::Two, |
561 | | command: Command::Proxy, |
562 | | protocol: Protocol::Unspecified, |
563 | | addresses: IPv6::new(source_address, destination_address, 256, 261).into(), |
564 | | }; |
565 | | let expected_tlvs = vec![Ok(TypeLengthValue::new(Type::CRC32C, &[5, 5]))]; |
566 | | |
567 | | let actual = Header::try_from(input.as_slice()).unwrap(); |
568 | | let actual_tlvs: Vec<Result<TypeLengthValue<'_>, ParseError>> = actual.tlvs().collect(); |
569 | | |
570 | | assert_eq!(actual, expected); |
571 | | assert_eq!(actual_tlvs, expected_tlvs); |
572 | | assert_eq!(actual.length(), 41); |
573 | | assert_eq!(actual.address_family(), AddressFamily::IPv6); |
574 | | assert_eq!( |
575 | | actual.address_bytes(), |
576 | | &[ |
577 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
578 | | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
579 | | 0xFF, 0xFF, 0xFF, 0xF1, 1, 0, 1, 5 |
580 | | ] |
581 | | ); |
582 | | assert_eq!(actual.tlv_bytes(), &[3, 0, 2, 5, 5]); |
583 | | assert_eq!(actual.as_bytes(), input.as_slice()); |
584 | | } |
585 | | |
586 | | #[test] |
587 | | fn partial_tlv() { |
588 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
589 | | |
590 | | input.extend_from_slice(PROTOCOL_PREFIX); |
591 | | input.push(0x21); |
592 | | input.push(0x11); |
593 | | input.extend([0, 15]); |
594 | | input.extend([127, 0, 0, 1]); |
595 | | input.extend([127, 0, 0, 2]); |
596 | | input.extend([0, 80]); |
597 | | input.extend([1, 187]); |
598 | | input.extend([1, 0, 1]); |
599 | | |
600 | | let header = Header::try_from(input.as_slice()).unwrap(); |
601 | | let mut tlvs = header.tlvs(); |
602 | | |
603 | | assert_eq!(tlvs.next().unwrap(), Err(ParseError::InvalidTLV(1, 1))); |
604 | | assert_eq!(tlvs.next(), None); |
605 | | } |
606 | | |
607 | | #[test] |
608 | | fn missing_tlvs() { |
609 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
610 | | |
611 | | input.extend_from_slice(PROTOCOL_PREFIX); |
612 | | input.push(0x21); |
613 | | input.push(0x11); |
614 | | input.extend([0, 17]); |
615 | | input.extend([127, 0, 0, 1]); |
616 | | input.extend([127, 0, 0, 2]); |
617 | | input.extend([0, 80]); |
618 | | input.extend([1, 187]); |
619 | | input.extend([1, 0, 1]); |
620 | | |
621 | | assert_eq!( |
622 | | Header::try_from(&input[..]).unwrap_err(), |
623 | | ParseError::Partial(15, 17) |
624 | | ); |
625 | | } |
626 | | |
627 | | #[test] |
628 | | fn partial_address() { |
629 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
630 | | |
631 | | input.extend_from_slice(PROTOCOL_PREFIX); |
632 | | input.push(0x21); |
633 | | input.push(0x11); |
634 | | input.extend([0, 12]); |
635 | | input.extend([127, 0, 0, 1]); |
636 | | input.extend([127, 0, 0, 2]); |
637 | | input.extend([0, 80]); |
638 | | |
639 | | assert_eq!( |
640 | | Header::try_from(&input[..]).unwrap_err(), |
641 | | ParseError::Partial(10, 12) |
642 | | ); |
643 | | } |
644 | | |
645 | | #[test] |
646 | | fn no_address() { |
647 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
648 | | |
649 | | input.extend_from_slice(PROTOCOL_PREFIX); |
650 | | input.push(0x20); |
651 | | input.push(0x02); |
652 | | input.extend([0, 0]); |
653 | | input.extend([0, 80]); |
654 | | |
655 | | let header = &input[..input.len() - 2]; |
656 | | let expected = Header { |
657 | | header: header.into(), |
658 | | version: Version::Two, |
659 | | command: Command::Local, |
660 | | protocol: Protocol::Datagram, |
661 | | addresses: Addresses::Unspecified, |
662 | | }; |
663 | | |
664 | | let actual = Header::try_from(input.as_slice()).unwrap(); |
665 | | let actual_tlvs: Vec<Result<TypeLengthValue<'_>, ParseError>> = actual.tlvs().collect(); |
666 | | |
667 | | assert_eq!(actual, expected); |
668 | | assert_eq!(actual_tlvs, vec![]); |
669 | | assert_eq!(actual.length(), 0); |
670 | | assert_eq!(actual.address_family(), AddressFamily::Unspecified); |
671 | | assert_eq!(actual.address_bytes(), &[]); |
672 | | assert_eq!(actual.tlv_bytes(), &[]); |
673 | | assert_eq!(actual.as_bytes(), header); |
674 | | } |
675 | | |
676 | | #[test] |
677 | | fn unspecified_address_family() { |
678 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
679 | | |
680 | | input.extend_from_slice(PROTOCOL_PREFIX); |
681 | | input.push(0x20); |
682 | | input.push(0x02); |
683 | | input.extend([0, 12]); |
684 | | input.extend([127, 0, 0, 1]); |
685 | | input.extend([127, 0, 0, 2]); |
686 | | input.extend([0, 80]); |
687 | | input.extend([0xbb, 1]); |
688 | | |
689 | | let expected = Header { |
690 | | header: input.as_slice().into(), |
691 | | version: Version::Two, |
692 | | command: Command::Local, |
693 | | protocol: Protocol::Datagram, |
694 | | addresses: Addresses::Unspecified, |
695 | | }; |
696 | | let actual = Header::try_from(input.as_slice()).unwrap(); |
697 | | |
698 | | assert_eq!(actual, expected); |
699 | | assert!(actual.tlvs().next().is_none()); |
700 | | assert_eq!(actual.length(), 12); |
701 | | assert_eq!(actual.address_family(), AddressFamily::Unspecified); |
702 | | assert_eq!( |
703 | | actual.address_bytes(), |
704 | | &[127, 0, 0, 1, 127, 0, 0, 2, 0, 80, 0xbb, 1] |
705 | | ); |
706 | | assert_eq!(actual.tlv_bytes(), &[]); |
707 | | assert_eq!(actual.as_bytes(), input.as_slice()); |
708 | | } |
709 | | |
710 | | #[test] |
711 | | fn missing_address() { |
712 | | let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len()); |
713 | | |
714 | | input.extend_from_slice(PROTOCOL_PREFIX); |
715 | | input.push(0x20); |
716 | | input.push(0x22); |
717 | | input.extend([0, 0]); |
718 | | input.extend([0, 80]); |
719 | | |
720 | | assert_eq!( |
721 | | Header::try_from(&input[..]).unwrap_err(), |
722 | | ParseError::InvalidAddresses(0, AddressFamily::IPv6.byte_length().unwrap_or_default()) |
723 | | ); |
724 | | } |
725 | | |
726 | | #[test] |
727 | | fn not_prefixed() { |
728 | | assert_eq!( |
729 | | Header::try_from(b"\r\n\r\n\x01\r\nQUIT\n".as_slice()).unwrap_err(), |
730 | | ParseError::Prefix |
731 | | ); |
732 | | assert_eq!( |
733 | | Header::try_from(b"\r\n\r\n\x01".as_slice()).unwrap_err(), |
734 | | ParseError::Prefix |
735 | | ); |
736 | | } |
737 | | |
738 | | #[test] |
739 | | fn incomplete() { |
740 | | assert_eq!( |
741 | | Header::try_from([0x0D, 0x0A, 0x0D, 0x0A, 0x00].as_slice()).unwrap_err(), |
742 | | ParseError::Incomplete(5) |
743 | | ); |
744 | | assert_eq!( |
745 | | Header::try_from(PROTOCOL_PREFIX).unwrap_err(), |
746 | | ParseError::Incomplete(PROTOCOL_PREFIX.len()) |
747 | | ); |
748 | | } |
749 | | } |