mirror of
https://github.com/smoltcp-rs/smoltcp.git
synced 2025-10-02 23:25:20 +00:00
ipv6: address scope and is_global_unicast
The scope of an address is used when selecting the source IPv6 address based on the destination address. As the scope is then also used for unicast address, I made the scope only public in the crate instead of outside the crate. Not sure if this should be public or not. This commit also adds the `is_global_unicast` query function for IPv6 addresses.
This commit is contained in:
parent
b310e3c366
commit
45f9838ad9
@ -25,6 +25,41 @@ pub const ADDR_SIZE: usize = 16;
|
|||||||
/// [RFC 8200 § 2]: https://www.rfc-editor.org/rfc/rfc4291#section-2
|
/// [RFC 8200 § 2]: https://www.rfc-editor.org/rfc/rfc4291#section-2
|
||||||
pub const IPV4_MAPPED_PREFIX_SIZE: usize = ADDR_SIZE - 4; // 4 == ipv4::ADDR_SIZE , cannot DRY here because of dependency on a IPv4 module which is behind the feature
|
pub const IPV4_MAPPED_PREFIX_SIZE: usize = ADDR_SIZE - 4; // 4 == ipv4::ADDR_SIZE , cannot DRY here because of dependency on a IPv4 module which is behind the feature
|
||||||
|
|
||||||
|
/// The [scope] of an address.
|
||||||
|
///
|
||||||
|
/// [scope]: https://www.rfc-editor.org/rfc/rfc4291#section-2.7
|
||||||
|
#[repr(u8)]
|
||||||
|
pub(crate) enum Scope {
|
||||||
|
/// Interface Local scope
|
||||||
|
InterfaceLocal = 0x1,
|
||||||
|
/// Link local scope
|
||||||
|
LinkLocal = 0x2,
|
||||||
|
/// Administratively configured
|
||||||
|
AdminLocal = 0x4,
|
||||||
|
/// Single site scope
|
||||||
|
SiteLocal = 0x5,
|
||||||
|
/// Organization scope
|
||||||
|
OrganizationLocal = 0x8,
|
||||||
|
/// Global scope
|
||||||
|
Global = 0xE,
|
||||||
|
/// Unknown scope
|
||||||
|
Unknown = 0xFF,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for Scope {
|
||||||
|
fn from(value: u8) -> Self {
|
||||||
|
match value {
|
||||||
|
0x1 => Self::InterfaceLocal,
|
||||||
|
0x2 => Self::LinkLocal,
|
||||||
|
0x4 => Self::AdminLocal,
|
||||||
|
0x5 => Self::SiteLocal,
|
||||||
|
0x8 => Self::OrganizationLocal,
|
||||||
|
0xE => Self::Global,
|
||||||
|
_ => Self::Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A sixteen-octet IPv6 address.
|
/// A sixteen-octet IPv6 address.
|
||||||
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
|
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
|
||||||
pub struct Address(pub [u8; ADDR_SIZE]);
|
pub struct Address(pub [u8; ADDR_SIZE]);
|
||||||
@ -143,6 +178,13 @@ impl Address {
|
|||||||
!(self.is_multicast() || self.is_unspecified())
|
!(self.is_multicast() || self.is_unspecified())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Query whether the IPv6 address is a [global unicast address].
|
||||||
|
///
|
||||||
|
/// [global unicast address]: https://datatracker.ietf.org/doc/html/rfc3587
|
||||||
|
pub const fn is_global_unicast(&self) -> bool {
|
||||||
|
(self.0[0] >> 5) == 0b001
|
||||||
|
}
|
||||||
|
|
||||||
/// Query whether the IPv6 address is a [multicast address].
|
/// Query whether the IPv6 address is a [multicast address].
|
||||||
///
|
///
|
||||||
/// [multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7
|
/// [multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7
|
||||||
@ -228,6 +270,22 @@ impl Address {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the scope of the address.
|
||||||
|
pub(crate) fn scope(&self) -> Scope {
|
||||||
|
if self.is_multicast() {
|
||||||
|
return Scope::from(self.as_bytes()[1] & 0b1111);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.is_link_local() {
|
||||||
|
Scope::LinkLocal
|
||||||
|
} else if self.is_unique_local() || self.is_global_unicast() {
|
||||||
|
// ULA are considered global scope
|
||||||
|
Scope::Global
|
||||||
|
} else {
|
||||||
|
Scope::Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert to an `IpAddress`.
|
/// Convert to an `IpAddress`.
|
||||||
///
|
///
|
||||||
/// Same as `.into()`, but works in `const`.
|
/// Same as `.into()`, but works in `const`.
|
||||||
@ -840,6 +898,7 @@ mod test {
|
|||||||
|
|
||||||
const LINK_LOCAL_ADDR: Address = Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
|
const LINK_LOCAL_ADDR: Address = Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
|
||||||
const UNIQUE_LOCAL_ADDR: Address = Address::new(0xfd00, 0, 0, 201, 1, 1, 1, 1);
|
const UNIQUE_LOCAL_ADDR: Address = Address::new(0xfd00, 0, 0, 201, 1, 1, 1, 1);
|
||||||
|
const GLOBAL_UNICAST_ADDR: Address = Address::new(0x2001, 0xdb8, 0x3, 0, 0, 0, 0, 1);
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic_multicast() {
|
fn test_basic_multicast() {
|
||||||
@ -848,11 +907,13 @@ mod test {
|
|||||||
assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_link_local());
|
assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_link_local());
|
||||||
assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_loopback());
|
assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_loopback());
|
||||||
assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_unique_local());
|
assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_unique_local());
|
||||||
|
assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_global_unicast());
|
||||||
assert!(!Address::LINK_LOCAL_ALL_NODES.is_unspecified());
|
assert!(!Address::LINK_LOCAL_ALL_NODES.is_unspecified());
|
||||||
assert!(Address::LINK_LOCAL_ALL_NODES.is_multicast());
|
assert!(Address::LINK_LOCAL_ALL_NODES.is_multicast());
|
||||||
assert!(!Address::LINK_LOCAL_ALL_NODES.is_link_local());
|
assert!(!Address::LINK_LOCAL_ALL_NODES.is_link_local());
|
||||||
assert!(!Address::LINK_LOCAL_ALL_NODES.is_loopback());
|
assert!(!Address::LINK_LOCAL_ALL_NODES.is_loopback());
|
||||||
assert!(!Address::LINK_LOCAL_ALL_NODES.is_unique_local());
|
assert!(!Address::LINK_LOCAL_ALL_NODES.is_unique_local());
|
||||||
|
assert!(!Address::LINK_LOCAL_ALL_NODES.is_global_unicast());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -862,6 +923,7 @@ mod test {
|
|||||||
assert!(LINK_LOCAL_ADDR.is_link_local());
|
assert!(LINK_LOCAL_ADDR.is_link_local());
|
||||||
assert!(!LINK_LOCAL_ADDR.is_loopback());
|
assert!(!LINK_LOCAL_ADDR.is_loopback());
|
||||||
assert!(!LINK_LOCAL_ADDR.is_unique_local());
|
assert!(!LINK_LOCAL_ADDR.is_unique_local());
|
||||||
|
assert!(!LINK_LOCAL_ADDR.is_global_unicast());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -871,6 +933,7 @@ mod test {
|
|||||||
assert!(!Address::LOOPBACK.is_link_local());
|
assert!(!Address::LOOPBACK.is_link_local());
|
||||||
assert!(Address::LOOPBACK.is_loopback());
|
assert!(Address::LOOPBACK.is_loopback());
|
||||||
assert!(!Address::LOOPBACK.is_unique_local());
|
assert!(!Address::LOOPBACK.is_unique_local());
|
||||||
|
assert!(!Address::LOOPBACK.is_global_unicast());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -880,6 +943,17 @@ mod test {
|
|||||||
assert!(!UNIQUE_LOCAL_ADDR.is_link_local());
|
assert!(!UNIQUE_LOCAL_ADDR.is_link_local());
|
||||||
assert!(!UNIQUE_LOCAL_ADDR.is_loopback());
|
assert!(!UNIQUE_LOCAL_ADDR.is_loopback());
|
||||||
assert!(UNIQUE_LOCAL_ADDR.is_unique_local());
|
assert!(UNIQUE_LOCAL_ADDR.is_unique_local());
|
||||||
|
assert!(!UNIQUE_LOCAL_ADDR.is_global_unicast());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_global_unicast() {
|
||||||
|
assert!(!GLOBAL_UNICAST_ADDR.is_unspecified());
|
||||||
|
assert!(!GLOBAL_UNICAST_ADDR.is_multicast());
|
||||||
|
assert!(!GLOBAL_UNICAST_ADDR.is_link_local());
|
||||||
|
assert!(!GLOBAL_UNICAST_ADDR.is_loopback());
|
||||||
|
assert!(!GLOBAL_UNICAST_ADDR.is_unique_local());
|
||||||
|
assert!(GLOBAL_UNICAST_ADDR.is_global_unicast());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -190,6 +190,8 @@ pub use self::ipv4::{
|
|||||||
Repr as Ipv4Repr, HEADER_LEN as IPV4_HEADER_LEN, MIN_MTU as IPV4_MIN_MTU,
|
Repr as Ipv4Repr, HEADER_LEN as IPV4_HEADER_LEN, MIN_MTU as IPV4_MIN_MTU,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "proto-ipv6")]
|
||||||
|
pub(crate) use self::ipv6::Scope as Ipv6AddressScope;
|
||||||
#[cfg(feature = "proto-ipv6")]
|
#[cfg(feature = "proto-ipv6")]
|
||||||
pub use self::ipv6::{
|
pub use self::ipv6::{
|
||||||
Address as Ipv6Address, Cidr as Ipv6Cidr, Packet as Ipv6Packet, Repr as Ipv6Repr,
|
Address as Ipv6Address, Cidr as Ipv6Cidr, Packet as Ipv6Packet, Repr as Ipv6Repr,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user