proxy_protocol/version2.rs
1use bytes::{Buf, BufMut as _, BytesMut};
2use snafu::{ensure, Snafu};
3use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
4
5#[derive(Debug, Snafu)]
6#[cfg_attr(test, derive(PartialEq, Eq))]
7pub enum ParseError {
8 #[snafu(display("an unexpected eof was hit"))]
9 UnexpectedEof,
10
11 #[snafu(display("invalid command: {}", cmd))]
12 UnknownCommand { cmd: u8 },
13
14 #[snafu(display("invalid address family: {}", family))]
15 UnknownAddressFamily { family: u8 },
16
17 #[snafu(display("invalid transport protocol: {}", protocol))]
18 UnknownTransportProtocol { protocol: u8 },
19
20 #[snafu(display("insufficient length specified: {}, requires minimum {}", given, needs))]
21 InsufficientLengthSpecified { given: usize, needs: usize },
22}
23
24#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
25pub enum ProxyCommand {
26 Local,
27 Proxy,
28}
29
30#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
31pub enum ProxyTransportProtocol {
32 Unspec,
33 Stream,
34 Datagram,
35}
36
37#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
38pub enum ProxyAddresses {
39 Unspec,
40 Ipv4 {
41 source: SocketAddrV4,
42 destination: SocketAddrV4,
43 },
44 Ipv6 {
45 source: SocketAddrV6,
46 destination: SocketAddrV6,
47 },
48 Unix {
49 source: [u8; 108],
50 destination: [u8; 108],
51 },
52}
53
54#[derive(PartialEq, Eq)]
55enum ProxyAddressFamily {
56 Unspec,
57 Inet,
58 Inet6,
59 Unix,
60}
61
62pub(crate) fn parse(buf: &mut impl Buf) -> Result<super::ProxyHeader, ParseError> {
63 // We need to parse the following:
64 //
65 // > struct proxy_hdr_v2 {
66 // > uint8_t sig[12]; /* hex 0D 0A 0D 0A 00 0D 0A 51 55 49 54 0A */
67 // > uint8_t ver_cmd; /* protocol version and command */
68 // > uint8_t fam; /* protocol family and address */
69 // > uint16_t len; /* number of following bytes part of the header */
70 // > };
71 //
72 // `uint8_t *sig` was parsed in our caller.
73 // We have ver_cmd next up; version is already parsed.
74
75 // No ensure for command byte. We know it must exist.
76 let command = buf.get_u8() << 4 >> 4;
77 let command = match command {
78 0 => ProxyCommand::Local,
79 1 => ProxyCommand::Proxy,
80 cmd => return UnknownCommand { cmd }.fail(),
81 };
82
83 // 4 bits for address family, 4 bits for transport protocol,
84 // then 2 bytes for the length.
85 ensure!(buf.remaining() >= 3, UnexpectedEof);
86
87 let byte = buf.get_u8();
88 let address_family = match byte >> 4 {
89 0 => ProxyAddressFamily::Unspec,
90 1 => ProxyAddressFamily::Inet,
91 2 => ProxyAddressFamily::Inet6,
92 3 => ProxyAddressFamily::Unix,
93 family => return UnknownAddressFamily { family }.fail(),
94 };
95 let transport_protocol = match byte << 4 >> 4 {
96 0 => ProxyTransportProtocol::Unspec,
97 1 => ProxyTransportProtocol::Stream,
98 2 => ProxyTransportProtocol::Datagram,
99 protocol => return UnknownTransportProtocol { protocol }.fail(),
100 };
101
102 let length = buf.get_u16() as usize;
103
104 if address_family == ProxyAddressFamily::Unspec {
105 // We have no information to parse.
106 ensure!(buf.remaining() >= length, UnexpectedEof);
107 buf.advance(length);
108
109 return Ok(super::ProxyHeader::Version2 {
110 command,
111 transport_protocol,
112 addresses: ProxyAddresses::Unspec,
113 });
114 }
115
116 // Time to parse the following:
117 //
118 // > union proxy_addr {
119 // > struct { /* for TCP/UDP over IPv4, len = 12 */
120 // > uint32_t src_addr;
121 // > uint32_t dst_addr;
122 // > uint16_t src_port;
123 // > uint16_t dst_port;
124 // > } ipv4_addr;
125 // > struct { /* for TCP/UDP over IPv6, len = 36 */
126 // > uint8_t src_addr[16];
127 // > uint8_t dst_addr[16];
128 // > uint16_t src_port;
129 // > uint16_t dst_port;
130 // > } ipv6_addr;
131 // > struct { /* for AF_UNIX sockets, len = 216 */
132 // > uint8_t src_addr[108];
133 // > uint8_t dst_addr[108];
134 // > } unix_addr;
135 // > };
136
137 if address_family == ProxyAddressFamily::Unix {
138 ensure!(
139 length >= 108 * 2,
140 InsufficientLengthSpecified {
141 given: length,
142 needs: 108usize * 2,
143 },
144 );
145 ensure!(buf.remaining() >= 108 * 2, UnexpectedEof);
146 let mut source = [0u8; 108];
147 let mut destination = [0u8; 108];
148 buf.copy_to_slice(&mut source[..]);
149 buf.copy_to_slice(&mut destination[..]);
150 // TODO(Mariell Hoversholm): Support TLVs
151 if length > 108 * 2 {
152 buf.advance(length - (108 * 2));
153 }
154
155 return Ok(super::ProxyHeader::Version2 {
156 command,
157 transport_protocol,
158 addresses: ProxyAddresses::Unix {
159 source,
160 destination,
161 },
162 });
163 }
164
165 let port_length = 4;
166 let address_length = match address_family {
167 ProxyAddressFamily::Inet => 8,
168 ProxyAddressFamily::Inet6 => 32,
169 _ => unreachable!(),
170 };
171
172 ensure!(
173 length >= port_length + address_length,
174 InsufficientLengthSpecified {
175 given: length,
176 needs: port_length + address_length,
177 },
178 );
179 ensure!(
180 buf.remaining() >= port_length + address_length,
181 UnexpectedEof,
182 );
183
184 let addresses = if address_family == ProxyAddressFamily::Inet {
185 let mut data = [0u8; 4];
186 buf.copy_to_slice(&mut data[..]);
187 let source = Ipv4Addr::from(data);
188
189 buf.copy_to_slice(&mut data);
190 let destination = Ipv4Addr::from(data);
191
192 let source_port = buf.get_u16();
193 let destination_port = buf.get_u16();
194
195 ProxyAddresses::Ipv4 {
196 source: SocketAddrV4::new(source, source_port),
197 destination: SocketAddrV4::new(destination, destination_port),
198 }
199 } else {
200 let mut data = [0u8; 16];
201 buf.copy_to_slice(&mut data);
202 let source = Ipv6Addr::from(data);
203
204 buf.copy_to_slice(&mut data);
205 let destination = Ipv6Addr::from(data);
206
207 let source_port = buf.get_u16();
208 let destination_port = buf.get_u16();
209
210 ProxyAddresses::Ipv6 {
211 source: SocketAddrV6::new(source, source_port, 0, 0),
212 destination: SocketAddrV6::new(destination, destination_port, 0, 0),
213 }
214 };
215
216 if length > port_length + address_length {
217 // TODO(Mariell Hoversholm): Implement TLVs
218 buf.advance(length - (port_length + address_length));
219 }
220
221 Ok(super::ProxyHeader::Version2 {
222 command,
223 transport_protocol,
224 addresses,
225 })
226}
227
228pub(crate) fn encode(
229 command: ProxyCommand,
230 transport_protocol: ProxyTransportProtocol,
231 addresses: ProxyAddresses,
232) -> BytesMut {
233 // > struct proxy_hdr_v2 {
234 // > uint8_t sig[12]; /* hex 0D 0A 0D 0A 00 0D 0A 51 55 49 54 0A */
235 // > uint8_t ver_cmd; /* protocol version and command */
236 // > uint8_t fam; /* protocol family and address */
237 // > uint16_t len; /* number of following bytes part of the header */
238 // > };
239 const SIG: [u8; 12] = [
240 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A,
241 ];
242
243 // > The next byte (the 13th one) is the protocol version and command.
244 // >
245 // > The highest four bits contains the version. As of this specification, it must
246 // > always be sent as \x2 and the receiver must only accept this value.
247 // >
248 // > The lowest four bits represents the command :
249 // > - \x0 : LOCAL : the connection was established on purpose by the proxy
250 // > without being relayed. The connection endpoints are the sender and the
251 // > receiver. Such connections exist when the proxy sends health-checks to the
252 // > server. The receiver must accept this connection as valid and must use the
253 // > real connection endpoints and discard the protocol block including the
254 // > family which is ignored.
255 // >
256 // > - \x1 : PROXY : the connection was established on behalf of another node,
257 // > and reflects the original connection endpoints. The receiver must then use
258 // > the information provided in the protocol block to get original the address.
259 // >
260 // > - other values are unassigned and must not be emitted by senders. Receivers
261 // > must drop connections presenting unexpected values here.
262 let ver_cmd = (2 << 4)
263 | match command {
264 ProxyCommand::Local => 0,
265 ProxyCommand::Proxy => 1,
266 };
267
268 // > The 14th byte contains the transport protocol and address family. The highest 4
269 // > bits contain the address family, the lowest 4 bits contain the protocol.
270 // >
271 // > The address family maps to the original socket family without necessarily
272 // > matching the values internally used by the system. It may be one of :
273 // >
274 // > - 0x0 : AF_UNSPEC : the connection is forwarded for an unknown, unspecified
275 // > or unsupported protocol. The sender should use this family when sending
276 // > LOCAL commands or when dealing with unsupported protocol families. The
277 // > receiver is free to accept the connection anyway and use the real endpoint
278 // > addresses or to reject it. The receiver should ignore address information.
279 // >
280 // > - 0x1 : AF_INET : the forwarded connection uses the AF_INET address family
281 // > (IPv4). The addresses are exactly 4 bytes each in network byte order,
282 // > followed by transport protocol information (typically ports).
283 // >
284 // > - 0x2 : AF_INET6 : the forwarded connection uses the AF_INET6 address family
285 // > (IPv6). The addresses are exactly 16 bytes each in network byte order,
286 // > followed by transport protocol information (typically ports).
287 // >
288 // > - 0x3 : AF_UNIX : the forwarded connection uses the AF_UNIX address family
289 // > (UNIX). The addresses are exactly 108 bytes each.
290 // >
291 // > - other values are unspecified and must not be emitted in version 2 of this
292 // > protocol and must be rejected as invalid by receivers.
293 // >
294 // > The transport protocol is specified in the lowest 4 bits of the 14th byte :
295 // >
296 // > - 0x0 : UNSPEC : the connection is forwarded for an unknown, unspecified
297 // > or unsupported protocol. The sender should use this family when sending
298 // > LOCAL commands or when dealing with unsupported protocol families. The
299 // > receiver is free to accept the connection anyway and use the real endpoint
300 // > addresses or to reject it. The receiver should ignore address information.
301 // >
302 // > - 0x1 : STREAM : the forwarded connection uses a SOCK_STREAM protocol (eg:
303 // > TCP or UNIX_STREAM). When used with AF_INET/AF_INET6 (TCP), the addresses
304 // > are followed by the source and destination ports represented on 2 bytes
305 // > each in network byte order.
306 // >
307 // > - 0x2 : DGRAM : the forwarded connection uses a SOCK_DGRAM protocol (eg:
308 // > UDP or UNIX_DGRAM). When used with AF_INET/AF_INET6 (UDP), the addresses
309 // > are followed by the source and destination ports represented on 2 bytes
310 // > each in network byte order.
311 // >
312 // > - other values are unspecified and must not be emitted in version 2 of this
313 // > protocol and must be rejected as invalid by receivers.
314 let fam = (match addresses {
315 ProxyAddresses::Unspec => 0,
316 ProxyAddresses::Ipv4 { .. } => 1,
317 ProxyAddresses::Ipv6 { .. } => 2,
318 ProxyAddresses::Unix { .. } => 3,
319 } << 4)
320 | match transport_protocol {
321 ProxyTransportProtocol::Unspec => 0,
322 ProxyTransportProtocol::Stream => 1,
323 ProxyTransportProtocol::Datagram => 2,
324 };
325
326 // > union proxy_addr {
327 // > struct { /* for TCP/UDP over IPv4, len = 12 */
328 // > uint32_t src_addr;
329 // > uint32_t dst_addr;
330 // > uint16_t src_port;
331 // > uint16_t dst_port;
332 // > } ipv4_addr;
333 // > struct { /* for TCP/UDP over IPv6, len = 36 */
334 // > uint8_t src_addr[16];
335 // > uint8_t dst_addr[16];
336 // > uint16_t src_port;
337 // > uint16_t dst_port;
338 // > } ipv6_addr;
339 // > struct { /* for AF_UNIX sockets, len = 216 */
340 // > uint8_t src_addr[108];
341 // > uint8_t dst_addr[108];
342 // > } unix_addr;
343 // > };
344 let len = match addresses {
345 ProxyAddresses::Unspec => 0,
346 ProxyAddresses::Unix { .. } => {
347 108 + 108
348 }
349 ProxyAddresses::Ipv4 { .. } => {
350 4 + 4 + 2 + 2
351 }
352 ProxyAddresses::Ipv6 { .. } => {
353 16 + 16 + 2 + 2
354 }
355 };
356
357 let mut buf = BytesMut::with_capacity(16 + len);
358 buf.put_slice(&SIG[..]);
359 buf.put_slice(&[ver_cmd, fam][..]);
360 buf.put_u16(len as u16);
361
362 match addresses {
363 ProxyAddresses::Unspec => (),
364 ProxyAddresses::Unix {
365 source,
366 destination,
367 } => {
368 buf.put_slice(&source[..]);
369 buf.put_slice(&destination[..]);
370 }
371 ProxyAddresses::Ipv4 {
372 source,
373 destination,
374 } => {
375 buf.put_slice(&source.ip().octets()[..]);
376 buf.put_slice(&destination.ip().octets()[..]);
377 buf.put_u16(source.port());
378 buf.put_u16(destination.port());
379 }
380 ProxyAddresses::Ipv6 {
381 source,
382 destination,
383 } => {
384 buf.put_slice(&source.ip().octets()[..]);
385 buf.put_slice(&destination.ip().octets()[..]);
386 buf.put_u16(source.port());
387 buf.put_u16(destination.port());
388 }
389 }
390
391 buf
392}
393
394#[cfg(test)]
395mod parse_tests {
396 use super::*;
397 use crate::ProxyHeader;
398 use bytes::{Bytes, BytesMut};
399 use pretty_assertions::assert_eq;
400 use rand::prelude::*;
401 use std::net::{Ipv4Addr, Ipv6Addr};
402
403 #[test]
404 fn test_unspec() {
405 assert_eq!(
406 parse(&mut &[0u8; 16][..]),
407 Ok(ProxyHeader::Version2 {
408 command: ProxyCommand::Local,
409 addresses: ProxyAddresses::Unspec,
410 transport_protocol: ProxyTransportProtocol::Unspec,
411 }),
412 );
413
414 let mut prefix = BytesMut::from(&[1u8][..]);
415 prefix.reserve(16);
416 prefix.extend_from_slice(&[0u8; 16][..]);
417 assert_eq!(
418 parse(&mut prefix),
419 Ok(ProxyHeader::Version2 {
420 command: ProxyCommand::Proxy,
421 addresses: ProxyAddresses::Unspec,
422 transport_protocol: ProxyTransportProtocol::Unspec,
423 }),
424 );
425 }
426
427 #[test]
428 fn test_ipv4() {
429 assert_eq!(
430 parse(
431 &mut &[
432 // Proxy command
433 1u8,
434 // Inet << 4 | Stream
435 (1 << 4) | 1,
436 // Length beyond this: 12
437 // Let's throw in a TLV with no data; 3 bytes.
438 0,
439 15,
440 // Source IP
441 127,
442 0,
443 0,
444 1,
445 // Destination IP
446 192,
447 168,
448 0,
449 1,
450 // Source port
451 // 65535 = [255, 255]
452 255,
453 255,
454 // Destination port
455 // 257 = [1, 1]
456 1,
457 1,
458 // TLV
459 69,
460 0,
461 0,
462 ][..]
463 ),
464 Ok(ProxyHeader::Version2 {
465 command: ProxyCommand::Proxy,
466 transport_protocol: ProxyTransportProtocol::Stream,
467 addresses: ProxyAddresses::Ipv4 {
468 source: SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 65535),
469 destination: SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 257),
470 },
471 })
472 );
473
474 let mut data = Bytes::from_static(
475 &[
476 // Local command
477 0u8,
478 // Inet << 4 | Datagram
479 (1 << 4) | 2,
480 // Length beyond this: 12
481 0,
482 12,
483 // Source IP
484 0,
485 0,
486 0,
487 0,
488 // Destination IP
489 255,
490 255,
491 255,
492 255,
493 // Source port
494 0,
495 0,
496 // Destination port
497 255,
498 0,
499 // Extra data
500 1,
501 2,
502 3,
503 4,
504 ][..],
505 );
506 assert_eq!(
507 parse(&mut data),
508 Ok(ProxyHeader::Version2 {
509 command: ProxyCommand::Local,
510 transport_protocol: ProxyTransportProtocol::Datagram,
511 addresses: ProxyAddresses::Ipv4 {
512 source: SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 0),
513 destination: SocketAddrV4::new(Ipv4Addr::new(255, 255, 255, 255), 255 << 8),
514 },
515 })
516 );
517 assert!(data.remaining() == 4); // Consume the entire header
518 }
519
520 #[test]
521 fn test_ipv6() {
522 assert_eq!(
523 parse(
524 &mut &[
525 // Proxy command
526 1u8,
527 // Inet6 << 4 | Datagram
528 (2 << 4) | 2,
529 // Length beyond this: 12
530 // Let's throw in a TLV with no data; 3 bytes.
531 0,
532 39,
533 // Source IP
534 255,
535 255,
536 255,
537 255,
538 255,
539 255,
540 255,
541 255,
542 255,
543 255,
544 255,
545 255,
546 255,
547 255,
548 255,
549 255,
550 // Destination IP
551 0,
552 0,
553 0,
554 0,
555 0,
556 0,
557 0,
558 0,
559 0,
560 0,
561 0,
562 0,
563 0,
564 0,
565 0,
566 0,
567 // Source port
568 // 65535 = [255, 255]
569 255,
570 255,
571 // Destination port
572 // 257 = [1, 1]
573 1,
574 1,
575 // TLV
576 69,
577 0,
578 0,
579 ][..]
580 ),
581 Ok(ProxyHeader::Version2 {
582 command: ProxyCommand::Proxy,
583 transport_protocol: ProxyTransportProtocol::Datagram,
584 addresses: ProxyAddresses::Ipv6 {
585 source: SocketAddrV6::new(
586 Ipv6Addr::new(65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535),
587 65535,
588 0,
589 0,
590 ),
591 destination: SocketAddrV6::new(
592 Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0),
593 257,
594 0,
595 0,
596 ),
597 },
598 })
599 );
600
601 let mut data = Bytes::from_static(
602 &[
603 // Local command
604 0u8,
605 // Inet6 << 4 | Stream
606 (2 << 4) | 1,
607 // Length beyond this: 12
608 0,
609 36,
610 // Source IP
611 81,
612 92,
613 0,
614 52,
615 83,
616 12,
617 255,
618 68,
619 19,
620 5,
621 111,
622 200,
623 54,
624 90,
625 55,
626 66,
627 // Destination IP
628 255,
629 255,
630 255,
631 255,
632 0,
633 0,
634 0,
635 0,
636 123,
637 123,
638 69,
639 69,
640 21,
641 21,
642 42,
643 42,
644 // Source port
645 123,
646 0,
647 // Destination port
648 255,
649 255,
650 // Extra data
651 1,
652 2,
653 3,
654 4,
655 ][..],
656 );
657 assert_eq!(
658 parse(&mut data),
659 Ok(ProxyHeader::Version2 {
660 command: ProxyCommand::Local,
661 transport_protocol: ProxyTransportProtocol::Stream,
662 addresses: ProxyAddresses::Ipv6 {
663 source: SocketAddrV6::new(
664 Ipv6Addr::new(20828, 52, 21260, 65348, 4869, 28616, 13914, 14146),
665 31488,
666 0,
667 0,
668 ),
669 destination: SocketAddrV6::new(
670 Ipv6Addr::new(65535, 65535, 0, 0, 31611, 17733, 5397, 10794),
671 65535,
672 0,
673 0,
674 ),
675 },
676 })
677 );
678 assert!(data.remaining() == 4); // Consume the entire header
679 }
680
681 #[test]
682 fn test_invalid_data() {
683 let mut data = [0u8; 200];
684 rand::thread_rng().fill_bytes(&mut data);
685 data[0] = 99; // Make 100% sure it's invalid.
686 assert!(parse(&mut &data[..]).is_err());
687
688 assert_eq!(parse(&mut &[0][..]), Err(ParseError::UnexpectedEof));
689
690 assert_eq!(
691 parse(
692 &mut &[
693 // Proxy command
694 1u8,
695 // Inet << 4 | Stream
696 (1 << 4) | 1,
697 // Length beyond this: 12
698 // 3 bytes is clearly too few if we expect 2 IPv4s and ports
699 0,
700 3,
701 ][..]
702 ),
703 Err(ParseError::InsufficientLengthSpecified {
704 given: 3,
705 needs: 4 * 2 + 2 * 2,
706 }),
707 );
708 }
709}
710
711#[cfg(test)]
712mod encode_tests {
713 use super::*;
714 use bytes::{Bytes, BytesMut};
715 use pretty_assertions::assert_eq;
716 use std::net::{Ipv4Addr, Ipv6Addr};
717
718 const SIG: [u8; 12] = [
719 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A,
720 ];
721
722 fn signed(buf: &[u8]) -> Bytes {
723 let mut bytes = BytesMut::from(&SIG[..]);
724 bytes.extend_from_slice(buf);
725 bytes.freeze()
726 }
727
728 #[test]
729 fn test_unspec() {
730 assert_eq!(
731 encode(
732 ProxyCommand::Local,
733 ProxyTransportProtocol::Unspec,
734 ProxyAddresses::Unspec,
735 ),
736 signed(&[(2 << 4) | 0, 0, 0, 0][..]),
737 );
738
739 assert_eq!(
740 encode(
741 ProxyCommand::Proxy,
742 ProxyTransportProtocol::Unspec,
743 ProxyAddresses::Unspec,
744 ),
745 signed(&[(2 << 4) | 1, 0, 0, 0][..]),
746 );
747 assert_eq!(
748 encode(
749 ProxyCommand::Proxy,
750 ProxyTransportProtocol::Unspec,
751 ProxyAddresses::Ipv4 {
752 source: SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 65535),
753 destination: SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 9012),
754 },
755 ),
756 signed(
757 &[
758 (2 << 4) | 1,
759 (1 << 4) | 0,
760 0,
761 12,
762 1,
763 2,
764 3,
765 4,
766 192,
767 168,
768 0,
769 1,
770 255,
771 255,
772 (9012u16 >> 8) as u8,
773 9012u16 as u8,
774 ][..]
775 ),
776 );
777 }
778
779 #[test]
780 fn test_ipv4() {
781 assert_eq!(
782 encode(
783 ProxyCommand::Proxy,
784 ProxyTransportProtocol::Stream,
785 ProxyAddresses::Ipv4 {
786 source: SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 65535),
787 destination: SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 9012),
788 },
789 ),
790 signed(
791 &[
792 (2 << 4) | 1,
793 (1 << 4) | 1,
794 0,
795 12,
796 1,
797 2,
798 3,
799 4,
800 192,
801 168,
802 0,
803 1,
804 255,
805 255,
806 (9012u16 >> 8) as u8,
807 9012u16 as u8,
808 ][..]
809 ),
810 );
811 assert_eq!(
812 encode(
813 ProxyCommand::Local,
814 ProxyTransportProtocol::Datagram,
815 ProxyAddresses::Ipv4 {
816 source: SocketAddrV4::new(Ipv4Addr::new(255, 255, 255, 255), 324),
817 destination: SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 2187),
818 },
819 ),
820 signed(
821 &[
822 (2 << 4) | 0,
823 (1 << 4) | 2,
824 0,
825 12,
826 255,
827 255,
828 255,
829 255,
830 192,
831 168,
832 0,
833 1,
834 (324u16 >> 8) as u8,
835 324u16 as u8,
836 (2187 >> 8) as u8,
837 2187u16 as u8,
838 ][..]
839 ),
840 );
841 }
842
843 #[test]
844 fn test_ipv6() {
845 assert_eq!(
846 encode(
847 ProxyCommand::Local,
848 ProxyTransportProtocol::Datagram,
849 ProxyAddresses::Ipv6 {
850 source: SocketAddrV6::new(
851 Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8),
852 8192,
853 0,
854 0,
855 ),
856 destination: SocketAddrV6::new(
857 Ipv6Addr::new(65535, 65535, 32767, 32766, 111, 222, 333, 444),
858 0,
859 0,
860 0,
861 ),
862 }
863 ),
864 signed(
865 &[
866 (2 << 4) | 0,
867 (2 << 4) | 2,
868 0,
869 36,
870 0,
871 1,
872 0,
873 2,
874 0,
875 3,
876 0,
877 4,
878 0,
879 5,
880 0,
881 6,
882 0,
883 7,
884 0,
885 8,
886 255,
887 255,
888 255,
889 255,
890 (32767u16 >> 8) as u8,
891 32767u16 as u8,
892 (32766u16 >> 8) as u8,
893 32766u16 as u8,
894 0,
895 111,
896 0,
897 222,
898 (333u16 >> 8) as u8,
899 333u16 as u8,
900 (444u16 >> 8) as u8,
901 444u16 as u8,
902 (8192u16 >> 8) as u8,
903 8192u16 as u8,
904 0,
905 0,
906 ][..]
907 ),
908 );
909 }
910}