rama_haproxy/protocol/v2/
model.rs1use crate::protocol::ip::{IPv4, IPv6};
2use crate::protocol::v2::error::ParseError;
3use std::borrow::Cow;
4use std::fmt;
5use std::net::SocketAddr;
6use std::ops::BitOr;
7
8pub const PROTOCOL_PREFIX: &[u8] = b"\r\n\r\n\0\r\nQUIT\n";
10pub(crate) const MINIMUM_LENGTH: usize = 16;
12pub(crate) const MINIMUM_TLV_LENGTH: usize = 3;
14
15const IPV4_ADDRESSES_BYTES: usize = 12;
17const IPV6_ADDRESSES_BYTES: usize = 36;
19const UNIX_ADDRESSES_BYTES: usize = 216;
21
22#[derive(Clone, Debug, PartialEq, Eq, Hash)]
46pub struct Header<'a> {
47 pub header: Cow<'a, [u8]>,
49 pub version: Version,
51 pub command: Command,
53 pub protocol: Protocol,
55 pub addresses: Addresses,
57}
58
59#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
61pub enum Version {
62 Two = 0x20,
64}
65
66#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
68pub enum Command {
69 Local = 0,
71 Proxy,
73}
74
75#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
77pub enum AddressFamily {
78 Unspecified = 0x00,
80 IPv4 = 0x10,
82 IPv6 = 0x20,
84 Unix = 0x30,
86}
87
88#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
90pub enum Protocol {
91 Unspecified = 0,
93 Stream,
95 Datagram,
97}
98
99#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
111pub enum Addresses {
112 Unspecified,
114 IPv4(IPv4),
116 IPv6(IPv6),
118 Unix(Unix),
120}
121
122#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
124pub struct Unix {
125 pub source: [u8; 108],
127 pub destination: [u8; 108],
129}
130
131#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
133pub struct TypeLengthValues<'a> {
134 bytes: &'a [u8],
135 offset: usize,
136}
137
138#[derive(Clone, Debug, PartialEq, Eq, Hash)]
140pub struct TypeLengthValue<'a> {
141 pub kind: Type,
144 pub value: Cow<'a, [u8]>,
146}
147
148rama_utils::macros::enums::enum_builder! {
149 @U8
155 pub enum Type {
156 ALPN => 0x01,
158 Authority => 0x02,
160 CRC32C => 0x03,
162 NoOp => 0x04,
164 UniqueId => 0x05,
166 SSL => 0x20,
168 SSLVersion => 0x21,
170 SSLCommonName => 0x22,
172 SSLCipher => 0x23,
174 SSLSignatureAlgorithm => 0x24,
176 SSLKeyAlgorithm => 0x25,
178 NetworkNamespace => 0x30,
180 }
181}
182
183impl fmt::Display for Header<'_> {
184 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185 write!(
186 f,
187 "{:?} {:#X} {:#X} ({} bytes)",
188 PROTOCOL_PREFIX,
189 self.version | self.command,
190 self.protocol | self.address_family(),
191 self.length()
192 )
193 }
194}
195
196impl Header<'_> {
197 #[must_use]
199 pub fn to_owned(&self) -> Header<'static> {
200 Header {
201 header: Cow::Owned(self.header.to_vec()),
202 version: self.version,
203 command: self.command,
204 protocol: self.protocol,
205 addresses: self.addresses,
206 }
207 }
208
209 #[must_use]
211 pub fn length(&self) -> usize {
212 self.header[MINIMUM_LENGTH..].len()
213 }
214
215 #[must_use]
217 pub fn len(&self) -> usize {
218 self.header.len()
219 }
220
221 #[must_use]
223 pub fn is_empty(&self) -> bool {
224 self.header.is_empty()
225 }
226
227 #[must_use]
229 pub fn address_family(&self) -> AddressFamily {
230 self.addresses.address_family()
231 }
232
233 fn address_bytes_end(&self) -> usize {
235 let length = self.length();
236 let address_bytes = self.address_family().byte_length().unwrap_or(length);
237
238 MINIMUM_LENGTH + std::cmp::min(address_bytes, length)
239 }
240
241 #[must_use]
243 pub fn address_bytes(&self) -> &[u8] {
244 &self.header[MINIMUM_LENGTH..self.address_bytes_end()]
245 }
246
247 #[must_use]
249 pub fn tlv_bytes(&self) -> &[u8] {
250 &self.header[self.address_bytes_end()..]
251 }
252
253 #[must_use]
255 pub fn tlvs(&self) -> TypeLengthValues<'_> {
256 TypeLengthValues {
257 bytes: self.tlv_bytes(),
258 offset: 0,
259 }
260 }
261
262 #[must_use]
264 pub fn as_bytes(&self) -> &[u8] {
265 self.header.as_ref()
266 }
267
268 #[must_use]
276 pub fn verify_crc32c(&self) -> Crc32cStatus {
277 let tlv_start = self.address_bytes_end();
286 let mut cursor = tlv_start;
287 for tlv in self.tlvs() {
288 let tlv = match tlv {
289 Ok(t) => t,
290 Err(e) => {
291 rama_core::telemetry::tracing::debug!(
292 error = %e,
293 "haproxy v2: TLV stream malformed before CRC32C TLV could be located",
294 );
295 return Crc32cStatus::MalformedBeforeCrc;
296 }
297 };
298 let value_start = cursor + MINIMUM_TLV_LENGTH;
299 let value_end = value_start + tlv.value.len();
300 if tlv.kind == Type::CRC32C {
301 let Ok(value) = <&[u8; 4]>::try_from(tlv.value.as_ref()) else {
302 rama_core::telemetry::tracing::debug!(
303 len = tlv.value.len(),
304 "haproxy v2: CRC32C TLV has unexpected value length (want 4)",
305 );
306 return Crc32cStatus::Invalid;
307 };
308 let expected = u32::from_be_bytes(*value);
309
310 let mut hasher = super::Crc32cHasher::new();
313 hasher.update(&self.header[..value_start]);
314 hasher.update(&[0u8; 4]);
315 hasher.update(&self.header[value_end..]);
316 return if hasher.finalize() == expected {
317 Crc32cStatus::Valid
318 } else {
319 Crc32cStatus::Invalid
320 };
321 }
322 cursor = value_end;
323 }
324 Crc32cStatus::Absent
325 }
326}
327
328#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
332pub enum Crc32cStatus {
333 Absent,
335 Valid,
337 Invalid,
340 MalformedBeforeCrc,
344}
345
346impl TypeLengthValues<'_> {
347 #[must_use]
349 pub fn as_bytes(&self) -> &[u8] {
350 self.bytes
351 }
352}
353
354impl<'a> From<&'a [u8]> for TypeLengthValues<'a> {
355 fn from(bytes: &'a [u8]) -> Self {
356 TypeLengthValues { bytes, offset: 0 }
357 }
358}
359
360impl<'a> Iterator for TypeLengthValues<'a> {
361 type Item = Result<TypeLengthValue<'a>, ParseError>;
362
363 fn next(&mut self) -> Option<Self::Item> {
364 if self.offset >= self.bytes.len() {
365 return None;
366 }
367
368 let remaining = &self.bytes[self.offset..];
369
370 if remaining.len() < MINIMUM_TLV_LENGTH {
371 self.offset = self.bytes.len();
372 return Some(Err(ParseError::Leftovers(self.bytes.len())));
373 }
374
375 let tlv_type = remaining[0];
376 let length = u16::from_be_bytes([remaining[1], remaining[2]]);
377 let tlv_length = MINIMUM_TLV_LENGTH + length as usize;
378
379 if remaining.len() < tlv_length {
380 self.offset = self.bytes.len();
381 return Some(Err(ParseError::InvalidTLV(tlv_type, length)));
382 }
383
384 self.offset += tlv_length;
385
386 Some(Ok(TypeLengthValue {
387 kind: Type::from(tlv_type),
388 value: Cow::Borrowed(&remaining[MINIMUM_TLV_LENGTH..tlv_length]),
389 }))
390 }
391}
392
393impl TypeLengthValues<'_> {
394 #[must_use]
396 pub fn len(&self) -> u16 {
397 self.bytes.len() as u16
398 }
399
400 #[must_use]
402 pub fn is_empty(&self) -> bool {
403 self.bytes.is_empty()
404 }
405}
406
407impl BitOr<Command> for Version {
408 type Output = u8;
409
410 fn bitor(self, command: Command) -> Self::Output {
411 (self as u8) | (command as u8)
412 }
413}
414
415impl BitOr<Version> for Command {
416 type Output = u8;
417
418 fn bitor(self, version: Version) -> Self::Output {
419 (self as u8) | (version as u8)
420 }
421}
422
423impl BitOr<Protocol> for AddressFamily {
424 type Output = u8;
425
426 fn bitor(self, protocol: Protocol) -> Self::Output {
427 (self as u8) | (protocol as u8)
428 }
429}
430
431impl AddressFamily {
432 #[must_use]
435 pub fn byte_length(&self) -> Option<usize> {
436 match self {
437 Self::IPv4 => Some(IPV4_ADDRESSES_BYTES),
438 Self::IPv6 => Some(IPV6_ADDRESSES_BYTES),
439 Self::Unix => Some(UNIX_ADDRESSES_BYTES),
440 Self::Unspecified => None,
441 }
442 }
443}
444
445impl From<AddressFamily> for u16 {
446 fn from(address_family: AddressFamily) -> Self {
447 address_family.byte_length().unwrap_or_default() as Self
448 }
449}
450
451impl From<(SocketAddr, SocketAddr)> for Addresses {
452 fn from(addresses: (SocketAddr, SocketAddr)) -> Self {
453 match addresses {
454 (SocketAddr::V4(source), SocketAddr::V4(destination)) => Self::IPv4(IPv4::new(
455 *source.ip(),
456 *destination.ip(),
457 source.port(),
458 destination.port(),
459 )),
460 (SocketAddr::V6(source), SocketAddr::V6(destination)) => Self::IPv6(IPv6::new(
461 *source.ip(),
462 *destination.ip(),
463 source.port(),
464 destination.port(),
465 )),
466 _ => Self::Unspecified,
467 }
468 }
469}
470
471impl From<IPv4> for Addresses {
472 fn from(addresses: IPv4) -> Self {
473 Self::IPv4(addresses)
474 }
475}
476
477impl From<IPv6> for Addresses {
478 fn from(addresses: IPv6) -> Self {
479 Self::IPv6(addresses)
480 }
481}
482
483impl From<Unix> for Addresses {
484 fn from(addresses: Unix) -> Self {
485 Self::Unix(addresses)
486 }
487}
488
489impl Addresses {
490 #[must_use]
492 pub fn address_family(&self) -> AddressFamily {
493 match self {
494 Self::Unspecified => AddressFamily::Unspecified,
495 Self::IPv4(..) => AddressFamily::IPv4,
496 Self::IPv6(..) => AddressFamily::IPv6,
497 Self::Unix(..) => AddressFamily::Unix,
498 }
499 }
500
501 #[must_use]
503 pub fn len(&self) -> usize {
504 self.address_family().byte_length().unwrap_or_default()
505 }
506
507 #[must_use]
510 pub fn is_empty(&self) -> bool {
511 self.address_family().byte_length().is_none()
512 }
513}
514
515impl Unix {
516 #[must_use]
518 pub const fn new(source: [u8; 108], destination: [u8; 108]) -> Self {
519 Self {
520 source,
521 destination,
522 }
523 }
524}
525
526impl BitOr<AddressFamily> for Protocol {
527 type Output = u8;
528
529 fn bitor(self, address_family: AddressFamily) -> Self::Output {
530 (self as u8) | (address_family as u8)
531 }
532}
533
534impl<'a, T: Into<Type>> From<(T, &'a [u8])> for TypeLengthValue<'a> {
535 fn from((kind, value): (T, &'a [u8])) -> Self {
536 TypeLengthValue {
537 kind: kind.into(),
538 value: value.into(),
539 }
540 }
541}
542
543impl<'a> TypeLengthValue<'a> {
544 #[must_use]
546 pub fn to_owned(&self) -> TypeLengthValue<'static> {
547 TypeLengthValue {
548 kind: self.kind,
549 value: Cow::Owned(self.value.to_vec()),
550 }
551 }
552
553 pub fn new<T: Into<Type>>(kind: T, value: &'a [u8]) -> Self {
556 TypeLengthValue {
557 kind: kind.into(),
558 value: value.into(),
559 }
560 }
561
562 #[must_use]
564 pub fn len(&self) -> usize {
565 self.value.len()
566 }
567
568 #[must_use]
570 pub fn is_empty(&self) -> bool {
571 self.value.is_empty()
572 }
573}