diff --git a/src/babel.rs b/src/babel.rs index 64bc30b..900be27 100644 --- a/src/babel.rs +++ b/src/babel.rs @@ -236,7 +236,7 @@ mod tests { .expect("64 is a valid IPv6 prefix size; qed"), [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, ] .into(), ); diff --git a/src/babel/seqno_request.rs b/src/babel/seqno_request.rs index 8fa979a..4160a86 100644 --- a/src/babel/seqno_request.rs +++ b/src/babel/seqno_request.rs @@ -15,7 +15,7 @@ use super::{AE_IPV4, AE_IPV6, AE_IPV6_LL, AE_WILDCARD}; const DEFAULT_HOP_COUNT: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(64) }; /// Base wire size of a [`SeqNoRequest`] without variable lenght address encoding. -const SEQNO_REQUEST_BASE_WIRE_SIZE: u8 = 38; +const SEQNO_REQUEST_BASE_WIRE_SIZE: u8 = 6 + RouterId::BYTE_SIZE as u8; /// Seqno request TLV body as defined in https://datatracker.ietf.org/doc/html/rfc8966#name-seqno-request #[derive(Debug, Clone, PartialEq)] @@ -95,9 +95,9 @@ impl SeqNoRequest { // Read "reserved" value, we assume this is 0 let _ = src.get_u8(); - let mut router_id_bytes = [0u8; 32]; - router_id_bytes.copy_from_slice(&src[..32]); - src.advance(32); + let mut router_id_bytes = [0u8; RouterId::BYTE_SIZE]; + router_id_bytes.copy_from_slice(&src[..RouterId::BYTE_SIZE]); + src.advance(RouterId::BYTE_SIZE); let router_id = RouterId::from(router_id_bytes); @@ -131,7 +131,7 @@ impl SeqNoRequest { _ => { // Invalid AE type, skip reamining data and ignore trace!("Invalid AE type in seqno_request packet, drop packet"); - src.advance(len as usize - 38); + src.advance(len as usize - 46); return None; } }; @@ -195,17 +195,17 @@ mod tests { hop_count: NonZeroU8::new(64).unwrap(), prefix: Subnet::new(Ipv6Addr::new(512, 25, 26, 27, 28, 0, 0, 29).into(), 64) .expect("64 is a valid IPv6 prefix size; qed"), - router_id: RouterId::from([1u8; 32]), + router_id: RouterId::from([1u8; RouterId::BYTE_SIZE]), }; snr.write_bytes(&mut buf); - assert_eq!(buf.len(), 46); + assert_eq!(buf.len(), 54); assert_eq!( - buf[..46], + buf[..54], [ 2, 64, 0, 17, 64, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 25, 0, 26, 0, 27, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 25, 0, 26, 0, 27, ] ); @@ -216,17 +216,17 @@ mod tests { hop_count: NonZeroU8::new(111).unwrap(), prefix: Subnet::new(Ipv4Addr::new(10, 101, 4, 1).into(), 32) .expect("32 is a valid IPv4 prefix size; qed"), - router_id: RouterId::from([2u8; 32]), + router_id: RouterId::from([2u8; RouterId::BYTE_SIZE]), }; snr.write_bytes(&mut buf); - assert_eq!(buf.len(), 42); + assert_eq!(buf.len(), 50); assert_eq!( - buf[..42], + buf[..50], [ 1, 32, 0, 170, 111, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 101, 4, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 101, 4, 1, ] ); } @@ -236,7 +236,7 @@ mod tests { let mut buf = bytes::BytesMut::from( &[ 0, 0, 0, 0, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, ][..], ); @@ -245,7 +245,7 @@ mod tests { seqno: 0.into(), prefix: Subnet::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).into(), 0) .expect("0 is a valid IPv6 prefix size; qed"), - router_id: RouterId::from([3u8; 32]), + router_id: RouterId::from([3u8; RouterId::BYTE_SIZE]), }; let buf_len = buf.len(); @@ -258,7 +258,8 @@ mod tests { let mut buf = bytes::BytesMut::from( &[ 3, 92, 0, 42, 232, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 10, 0, 20, 0, 30, 0, 40, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 10, 0, 20, 0, 30, 0, + 40, ][..], ); @@ -267,7 +268,7 @@ mod tests { hop_count: NonZeroU8::new(232).unwrap(), prefix: Subnet::new(Ipv6Addr::new(0xfe80, 0, 0, 0, 10, 20, 30, 40).into(), 92) .expect("92 is a valid IPv6 prefix size; qed"), - router_id: RouterId::from([4u8; 32]), + router_id: RouterId::from([4u8; RouterId::BYTE_SIZE]), }; let buf_len = buf.len(); @@ -285,8 +286,8 @@ mod tests { let mut buf = bytes::BytesMut::from( &[ 4, 64, 0, 0, 44, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, ][..], ); @@ -307,7 +308,8 @@ mod tests { let mut buf = bytes::BytesMut::from( &[ 3, 64, 92, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 10, 0, 20, 0, 30, 0, 40, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 10, 0, 20, 0, 30, 0, + 40, ][..], ); @@ -325,7 +327,7 @@ mod tests { let seqno_src = super::SeqNoRequest::new( 64.into(), - RouterId::from([6; 32]), + RouterId::from([6; RouterId::BYTE_SIZE]), Subnet::new( Ipv6Addr::new(0x21f, 0x4025, 0xabcd, 0xdead, 0, 0, 0, 0).into(), 64, diff --git a/src/babel/update.rs b/src/babel/update.rs index 2affc6c..c70af09 100644 --- a/src/babel/update.rs +++ b/src/babel/update.rs @@ -19,7 +19,7 @@ const UPDATE_FLAG_ROUTER_ID: u8 = 0x40; const FLAG_MASK: u8 = 0b1100_0000; /// Base wire size of an [`Update`] without variable lenght address encoding. -const UPDATE_BASE_WIRE_SIZE: u8 = 10 + 32; +const UPDATE_BASE_WIRE_SIZE: u8 = 10 + RouterId::BYTE_SIZE as u8; /// Update TLV body as defined in https://datatracker.ietf.org/doc/html/rfc8966#name-update. #[derive(Debug, Clone, PartialEq)] @@ -141,9 +141,9 @@ impl Update { let subnet = Subnet::new(prefix, plen).ok()?; - let mut router_id_bytes = [0u8; 32]; - router_id_bytes.copy_from_slice(&src[..32]); - src.advance(32); + let mut router_id_bytes = [0u8; RouterId::BYTE_SIZE]; + router_id_bytes.copy_from_slice(&src[..RouterId::BYTE_SIZE]); + src.advance(RouterId::BYTE_SIZE); let router_id = RouterId::from(router_id_bytes); @@ -198,18 +198,18 @@ mod tests { metric: 25.into(), subnet: Subnet::new(Ipv6Addr::new(512, 25, 26, 27, 28, 0, 0, 29).into(), 64) .expect("64 is a valid IPv6 prefix size; qed"), - router_id: RouterId::from([1u8; 32]), + router_id: RouterId::from([1u8; RouterId::BYTE_SIZE]), }; ihu.write_bytes(&mut buf); - assert_eq!(buf.len(), 58); + assert_eq!(buf.len(), 66); assert_eq!( - buf[..58], + buf[..66], [ 2, 192, 64, 0, 1, 144, 0, 17, 0, 25, 2, 0, 0, 25, 0, 26, 0, 27, 0, 28, 0, 0, 0, 0, 0, 29, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ] ); @@ -222,17 +222,18 @@ mod tests { metric: 256.into(), subnet: Subnet::new(Ipv4Addr::new(10, 101, 4, 1).into(), 32) .expect("32 is a valid IPv4 prefix size; qed"), - router_id: RouterId::from([2u8; 32]), + router_id: RouterId::from([2u8; RouterId::BYTE_SIZE]), }; ihu.write_bytes(&mut buf); - assert_eq!(buf.len(), 46); + assert_eq!(buf.len(), 54); assert_eq!( - buf[..46], + buf[..54], [ 1, 0, 32, 0, 2, 88, 0, 170, 1, 0, 10, 101, 4, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2 ] ); } @@ -242,7 +243,7 @@ mod tests { let mut buf = bytes::BytesMut::from( &[ 0, 64, 0, 0, 0, 100, 0, 70, 2, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, ][..], ); @@ -253,7 +254,7 @@ mod tests { metric: 512.into(), subnet: Subnet::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).into(), 0) .expect("0 is a valid IPv6 prefix size; qed"), - router_id: RouterId::from([3u8; 32]), + router_id: RouterId::from([3u8; RouterId::BYTE_SIZE]), }; let buf_len = buf.len(); @@ -266,7 +267,8 @@ mod tests { let mut buf = bytes::BytesMut::from( &[ 3, 0, 92, 0, 3, 232, 0, 42, 3, 1, 0, 10, 0, 20, 0, 30, 0, 40, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, ][..], ); @@ -277,7 +279,7 @@ mod tests { metric: 769.into(), subnet: Subnet::new(Ipv6Addr::new(0xfe80, 0, 0, 0, 10, 20, 30, 40).into(), 92) .expect("92 is a valid IPv6 prefix size; qed"), - router_id: RouterId::from([4u8; 32]), + router_id: RouterId::from([4u8; RouterId::BYTE_SIZE]), }; let buf_len = buf.len(); @@ -296,7 +298,7 @@ mod tests { &[ 4, 0, 64, 0, 0, 44, 2, 0, 0, 10, 10, 5, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, ][..], ); @@ -314,7 +316,8 @@ mod tests { let mut buf = bytes::BytesMut::from( &[ 3, 255, 92, 0, 3, 232, 0, 42, 3, 1, 0, 10, 0, 20, 0, 30, 0, 40, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, ][..], ); @@ -325,7 +328,7 @@ mod tests { metric: 769.into(), subnet: Subnet::new(Ipv6Addr::new(0xfe80, 0, 0, 0, 10, 20, 30, 40).into(), 92) .expect("92 is a valid IPv6 prefix size; qed"), - router_id: RouterId::from([4u8; 32]), + router_id: RouterId::from([4u8; RouterId::BYTE_SIZE]), }; let buf_len = buf.len(); @@ -349,7 +352,7 @@ mod tests { 64, ) .expect("64 is a valid IPv6 prefix size; qed"), - RouterId::from([6; 32]), + RouterId::from([6; RouterId::BYTE_SIZE]), ); hello_src.write_bytes(&mut buf); let buf_len = buf.len(); diff --git a/src/router.rs b/src/router.rs index 7ea3131..965d07a 100644 --- a/src/router.rs +++ b/src/router.rs @@ -78,10 +78,12 @@ impl Router { inner_w.append(RouterOpLogEntry::SetStaticRoutes(static_routes)); inner_w.publish(); + let router_id = RouterId::new(node_keypair.1); + let router = Router { inner_w: Arc::new(Mutex::new(inner_w)), inner_r, - router_id: RouterId::new(node_keypair.1), + router_id, node_keypair, router_data_tx, router_control_tx, @@ -102,10 +104,7 @@ impl Router { tokio::spawn(Router::propagate_static_route(router.clone())); tokio::spawn(Router::propagate_selected_routes(router.clone())); - tokio::spawn(Router::check_for_dead_peers( - router.clone(), - RouterId::new(router.node_keypair.1), - )); + tokio::spawn(Router::check_for_dead_peers(router.clone(), router_id)); tokio::spawn(Router::process_expired_source_keys( router.clone(), diff --git a/src/router_id.rs b/src/router_id.rs index 2523714..0002efc 100644 --- a/src/router_id.rs +++ b/src/router_id.rs @@ -4,33 +4,57 @@ use crate::crypto::PublicKey; /// A `RouterId` uniquely identifies a router in the network. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct RouterId(PublicKey); +pub struct RouterId { + pk: PublicKey, + zone: [u8; 2], + rnd: [u8; 6], +} impl RouterId { + /// Size in bytes of a `RouterId` + pub const BYTE_SIZE: usize = 40; + /// Create a new `RouterId` from a [`PublicKey`]. pub fn new(pk: PublicKey) -> Self { - Self(pk) + Self { + pk, + zone: [0; 2], + rnd: rand::random(), + } } /// View this `RouterId` as a byte array. - pub fn as_bytes(&self) -> &[u8; 32] { - self.0.as_bytes() + pub fn as_bytes(&self) -> [u8; Self::BYTE_SIZE] { + let mut out = [0; Self::BYTE_SIZE]; + out[..32].copy_from_slice(self.pk.as_bytes()); + out[32..34].copy_from_slice(&self.zone); + out[34..].copy_from_slice(&self.rnd); + out } /// Converts this `RouterId` to a [`PublicKey`]. pub fn to_pubkey(self) -> PublicKey { - self.0 + self.pk } } -impl From<[u8; 32]> for RouterId { - fn from(bytes: [u8; 32]) -> RouterId { - RouterId(PublicKey::from(bytes)) +impl From<[u8; Self::BYTE_SIZE]> for RouterId { + fn from(bytes: [u8; Self::BYTE_SIZE]) -> RouterId { + RouterId { + pk: PublicKey::from(<&[u8] as TryInto<[u8; 32]>>::try_into(&bytes[..32]).unwrap()), + zone: bytes[32..34].try_into().unwrap(), + rnd: bytes[34..Self::BYTE_SIZE].try_into().unwrap(), + } } } impl fmt::Display for RouterId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_fmt(format_args!("{}", self.0)) + let RouterId { pk, zone, rnd } = self; + f.write_fmt(format_args!( + "{pk}-{}-{}", + faster_hex::hex_string(zone), + faster_hex::hex_string(rnd) + )) } }