Procházet zdrojové kódy

wire: use core::net::Ipv6Addr as the ipv6 address type.

Dario Nieuwenhuis před 6 měsíci
rodič
revize
803fa8734a

+ 4 - 8
benches/bench.rs

@@ -13,13 +13,9 @@ mod wire {
     extern crate test;
 
     #[cfg(feature = "proto-ipv6")]
-    const SRC_ADDR: IpAddress = IpAddress::Ipv6(Ipv6Address([
-        0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
-    ]));
+    const SRC_ADDR: IpAddress = IpAddress::Ipv6(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1));
     #[cfg(feature = "proto-ipv6")]
-    const DST_ADDR: IpAddress = IpAddress::Ipv6(Ipv6Address([
-        0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
-    ]));
+    const DST_ADDR: IpAddress = IpAddress::Ipv6(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2));
 
     #[cfg(all(not(feature = "proto-ipv6"), feature = "proto-ipv4"))]
     const SRC_ADDR: IpAddress = IpAddress::Ipv4(Ipv4Address::new(192, 168, 1, 1));
@@ -102,8 +98,8 @@ mod wire {
     #[cfg(feature = "proto-ipv6")]
     fn bench_emit_ipv6(b: &mut test::Bencher) {
         let repr = Ipv6Repr {
-            src_addr: Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
-            dst_addr: Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]),
+            src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
+            dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2),
             next_header: IpProtocol::Tcp,
             payload_len: 100,
             hop_limit: 64,

+ 6 - 9
examples/multicast6.rs

@@ -19,9 +19,9 @@ use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv6Address};
 // will send packets to the multicast group we join below on tap0.
 
 const PORT: u16 = 8123;
-const GROUP: [u16; 8] = [0xff02, 0, 0, 0, 0, 0, 0, 0x1234];
-const LOCAL_ADDR: [u16; 8] = [0xfe80, 0, 0, 0, 0, 0, 0, 0x101];
-const ROUTER_ADDR: [u16; 8] = [0xfe80, 0, 0, 0, 0, 0, 0, 0x100];
+const GROUP: Ipv6Address = Ipv6Address::new(0xff02, 0, 0, 0, 0, 0, 0, 0x1234);
+const LOCAL_ADDR: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x101);
+const ROUTER_ADDR: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x100);
 
 fn main() {
     utils::setup_logging("warn");
@@ -37,7 +37,6 @@ fn main() {
         utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false);
 
     // Create interface
-    let local_addr = Ipv6Address::from_parts(&LOCAL_ADDR);
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]);
     let mut config = match device.capabilities().medium {
         Medium::Ethernet => Config::new(ethernet_addr.into()),
@@ -49,12 +48,12 @@ fn main() {
     let mut iface = Interface::new(config, &mut device, Instant::now());
     iface.update_ip_addrs(|ip_addrs| {
         ip_addrs
-            .push(IpCidr::new(IpAddress::from(local_addr), 64))
+            .push(IpCidr::new(IpAddress::from(LOCAL_ADDR), 64))
             .unwrap();
     });
     iface
         .routes_mut()
-        .add_default_ipv6_route(Ipv6Address::from_parts(&ROUTER_ADDR))
+        .add_default_ipv6_route(ROUTER_ADDR)
         .unwrap();
 
     // Create sockets
@@ -65,9 +64,7 @@ fn main() {
     let udp_handle = sockets.add(udp_socket);
 
     // Join a multicast group
-    iface
-        .join_multicast_group(Ipv6Address::from_parts(&GROUP))
-        .unwrap();
+    iface.join_multicast_group(GROUP).unwrap();
 
     loop {
         let timestamp = Instant::now();

+ 5 - 5
src/iface/interface/ipv6.rs

@@ -58,7 +58,7 @@ impl InterfaceInner {
         fn common_prefix_length(dst_addr: &Ipv6Cidr, src_addr: &Ipv6Address) -> usize {
             let addr = dst_addr.address();
             let mut bits = 0;
-            for (l, r) in addr.as_bytes().iter().zip(src_addr.as_bytes().iter()) {
+            for (l, r) in addr.octets().iter().zip(src_addr.octets().iter()) {
                 if l == r {
                     bits += 8;
                 } else {
@@ -82,7 +82,7 @@ impl InterfaceInner {
                 .count()
                 == 0
         {
-            return Ipv6Address::LOOPBACK;
+            return Ipv6Address::LOCALHOST;
         }
 
         let mut candidate = self
@@ -147,10 +147,10 @@ impl InterfaceInner {
     pub fn has_solicited_node(&self, addr: Ipv6Address) -> bool {
         self.ip_addrs.iter().any(|cidr| {
             match *cidr {
-                IpCidr::Ipv6(cidr) if cidr.address() != Ipv6Address::LOOPBACK => {
+                IpCidr::Ipv6(cidr) if cidr.address() != Ipv6Address::LOCALHOST => {
                     // Take the lower order 24 bits of the IPv6 address and
                     // append those bits to FF02:0:0:0:0:1:FF00::/104.
-                    addr.as_bytes()[14..] == cidr.address().as_bytes()[14..]
+                    addr.octets()[14..] == cidr.address().octets()[14..]
                 }
                 _ => false,
             }
@@ -524,7 +524,7 @@ impl InterfaceInner {
 
         // Per [RFC 3810 § 5.2.14], all MLDv2 reports are sent to ff02::16.
         // [RFC 3810 § 5.2.14]: https://tools.ietf.org/html/rfc3810#section-5.2.14
-        let dst_addr = Ipv6Address::LINK_LOCAL_ALL_MLDV2_ROUTERS;
+        let dst_addr = IPV6_LINK_LOCAL_ALL_MLDV2_ROUTERS;
 
         // Create a dummy IPv6 extension header so we can calculate the total length of the packet.
         // The actual extension header will be created later by Packet::emit_payload().

+ 3 - 3
src/iface/interface/mod.rs

@@ -832,10 +832,10 @@ impl InterfaceInner {
             #[cfg(feature = "proto-ipv4")]
             IpAddress::Ipv4(key) => key == IPV4_MULTICAST_ALL_SYSTEMS,
             #[cfg(feature = "proto-rpl")]
-            IpAddress::Ipv6(Ipv6Address::LINK_LOCAL_ALL_RPL_NODES) => true,
+            IpAddress::Ipv6(IPV6_LINK_LOCAL_ALL_RPL_NODES) => true,
             #[cfg(feature = "proto-ipv6")]
             IpAddress::Ipv6(key) => {
-                key == Ipv6Address::LINK_LOCAL_ALL_NODES || self.has_solicited_node(key)
+                key == IPV6_LINK_LOCAL_ALL_NODES || self.has_solicited_node(key)
             }
             #[allow(unreachable_patterns)]
             _ => false,
@@ -1011,7 +1011,7 @@ impl InterfaceInner {
                 IpAddress::Ipv6(addr) => match self.caps.medium {
                     #[cfg(feature = "medium-ethernet")]
                     Medium::Ethernet => {
-                        let b = addr.as_bytes();
+                        let b = addr.octets();
                         HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[
                             0x33, 0x33, b[12], b[13], b[14], b[15],
                         ]))

+ 65 - 67
src/iface/interface/tests/ipv6.rs

@@ -49,8 +49,8 @@ fn any_ip(#[case] medium: Medium) {
         parse_ipv6(&data),
         Ok(Packet::new_ipv6(
             Ipv6Repr {
-                src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
-                dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0003]),
+                src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002),
+                dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0003),
                 hop_limit: 64,
                 next_header: IpProtocol::Icmpv6,
                 payload_len: 8,
@@ -73,9 +73,7 @@ fn any_ip(#[case] medium: Medium) {
                     Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0),
                     64,
                 )),
-                via_router: IpAddress::Ipv6(Ipv6Address::from_parts(&[
-                    0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001,
-                ])),
+                via_router: IpAddress::Ipv6(Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001)),
                 preferred_until: None,
                 expires_at: None,
             })
@@ -157,8 +155,8 @@ fn hop_by_hop_skip_with_icmp(#[case] medium: Medium) {
 
     let response = Some(Packet::new_ipv6(
         Ipv6Repr {
-            src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
-            dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
+            src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001),
+            dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002),
             hop_limit: 64,
             next_header: IpProtocol::Icmpv6,
             payload_len: 19,
@@ -350,8 +348,8 @@ fn imcp_empty_echo_request(#[case] medium: Medium) {
         parse_ipv6(&data),
         Ok(Packet::new_ipv6(
             Ipv6Repr {
-                src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
-                dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
+                src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002),
+                dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001),
                 hop_limit: 64,
                 next_header: IpProtocol::Icmpv6,
                 payload_len: 8,
@@ -366,8 +364,8 @@ fn imcp_empty_echo_request(#[case] medium: Medium) {
 
     let response = Some(Packet::new_ipv6(
         Ipv6Repr {
-            src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
-            dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
+            src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001),
+            dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002),
             hop_limit: 64,
             next_header: IpProtocol::Icmpv6,
             payload_len: 8,
@@ -411,8 +409,8 @@ fn icmp_echo_request(#[case] medium: Medium) {
         parse_ipv6(&data),
         Ok(Packet::new_ipv6(
             Ipv6Repr {
-                src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
-                dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
+                src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002),
+                dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001),
                 hop_limit: 64,
                 next_header: IpProtocol::Icmpv6,
                 payload_len: 19,
@@ -427,8 +425,8 @@ fn icmp_echo_request(#[case] medium: Medium) {
 
     let response = Some(Packet::new_ipv6(
         Ipv6Repr {
-            src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
-            dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
+            src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001),
+            dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002),
             hop_limit: 64,
             next_header: IpProtocol::Icmpv6,
             payload_len: 19,
@@ -472,8 +470,8 @@ fn icmp_echo_reply_as_input(#[case] medium: Medium) {
         parse_ipv6(&data),
         Ok(Packet::new_ipv6(
             Ipv6Repr {
-                src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
-                dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
+                src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002),
+                dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001),
                 hop_limit: 64,
                 next_header: IpProtocol::Icmpv6,
                 payload_len: 19,
@@ -517,8 +515,8 @@ fn unknown_proto_with_multicast_dst_address(#[case] medium: Medium) {
 
     let response = Some(Packet::new_ipv6(
         Ipv6Repr {
-            src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
-            dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
+            src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001),
+            dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002),
             hop_limit: 64,
             next_header: IpProtocol::Icmpv6,
             payload_len: 48,
@@ -527,8 +525,8 @@ fn unknown_proto_with_multicast_dst_address(#[case] medium: Medium) {
             reason: Icmpv6ParamProblem::UnrecognizedNxtHdr,
             pointer: 40,
             header: Ipv6Repr {
-                src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
-                dst_addr: Ipv6Address::from_parts(&[0xff02, 0, 0, 0, 0, 0, 0, 0x0001]),
+                src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002),
+                dst_addr: Ipv6Address::new(0xff02, 0, 0, 0, 0, 0, 0, 0x0001),
                 hop_limit: 64,
                 next_header: IpProtocol::Unknown(0x0c),
                 payload_len: 0,
@@ -567,8 +565,8 @@ fn unknown_proto(#[case] medium: Medium) {
 
     let response = Some(Packet::new_ipv6(
         Ipv6Repr {
-            src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
-            dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
+            src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001),
+            dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002),
             hop_limit: 64,
             next_header: IpProtocol::Icmpv6,
             payload_len: 48,
@@ -577,8 +575,8 @@ fn unknown_proto(#[case] medium: Medium) {
             reason: Icmpv6ParamProblem::UnrecognizedNxtHdr,
             pointer: 40,
             header: Ipv6Repr {
-                src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
-                dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
+                src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002),
+                dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001),
                 hop_limit: 64,
                 next_header: IpProtocol::Unknown(0x0c),
                 payload_len: 0,
@@ -616,15 +614,15 @@ fn ndsic_neighbor_advertisement_ethernet(#[case] medium: Medium) {
         parse_ipv6(&data),
         Ok(Packet::new_ipv6(
             Ipv6Repr {
-                src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
-                dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
+                src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002),
+                dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001),
                 hop_limit: 255,
                 next_header: IpProtocol::Icmpv6,
                 payload_len: 32,
             },
             IpPayload::Icmpv6(Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert {
                 flags: NdiscNeighborFlags::SOLICITED,
-                target_addr: Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0, 0, 0, 0x0002]),
+                target_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x0002),
                 lladdr: Some(RawHardwareAddress::from_bytes(&[0, 0, 0, 0, 0, 1])),
             }))
         ))
@@ -646,7 +644,7 @@ fn ndsic_neighbor_advertisement_ethernet(#[case] medium: Medium) {
 
     assert_eq!(
         iface.inner.neighbor_cache.lookup(
-            &IpAddress::Ipv6(Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002])),
+            &IpAddress::Ipv6(Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002)),
             iface.inner.now,
         ),
         NeighborAnswer::Found(HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[
@@ -671,15 +669,15 @@ fn ndsic_neighbor_advertisement_ethernet_multicast_addr(#[case] medium: Medium)
         parse_ipv6(&data),
         Ok(Packet::new_ipv6(
             Ipv6Repr {
-                src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
-                dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
+                src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002),
+                dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001),
                 hop_limit: 255,
                 next_header: IpProtocol::Icmpv6,
                 payload_len: 32,
             },
             IpPayload::Icmpv6(Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert {
                 flags: NdiscNeighborFlags::SOLICITED,
-                target_addr: Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0, 0, 0, 0x0002]),
+                target_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x0002),
                 lladdr: Some(RawHardwareAddress::from_bytes(&[
                     0xff, 0xff, 0xff, 0xff, 0xff, 0xff
                 ])),
@@ -703,7 +701,7 @@ fn ndsic_neighbor_advertisement_ethernet_multicast_addr(#[case] medium: Medium)
 
     assert_eq!(
         iface.inner.neighbor_cache.lookup(
-            &IpAddress::Ipv6(Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002])),
+            &IpAddress::Ipv6(Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002)),
             iface.inner.now,
         ),
         NeighborAnswer::NotFound,
@@ -726,15 +724,15 @@ fn ndsic_neighbor_advertisement_ieee802154(#[case] medium: Medium) {
         parse_ipv6(&data),
         Ok(Packet::new_ipv6(
             Ipv6Repr {
-                src_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002]),
-                dst_addr: Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001]),
+                src_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002),
+                dst_addr: Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0001),
                 hop_limit: 255,
                 next_header: IpProtocol::Icmpv6,
                 payload_len: 40,
             },
             IpPayload::Icmpv6(Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert {
                 flags: NdiscNeighborFlags::SOLICITED,
-                target_addr: Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0, 0, 0, 0x0002]),
+                target_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x0002),
                 lladdr: Some(RawHardwareAddress::from_bytes(&[0, 0, 0, 0, 0, 0, 0, 1])),
             }))
         ))
@@ -756,7 +754,7 @@ fn ndsic_neighbor_advertisement_ieee802154(#[case] medium: Medium) {
 
     assert_eq!(
         iface.inner.neighbor_cache.lookup(
-            &IpAddress::Ipv6(Ipv6Address::from_parts(&[0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002])),
+            &IpAddress::Ipv6(Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 0x0002)),
             iface.inner.now,
         ),
         NeighborAnswer::Found(HardwareAddress::Ieee802154(Ieee802154Address::from_bytes(
@@ -1004,8 +1002,8 @@ fn get_source_address() {
         Ipv6Address::new(0x2001, 0x0db9, 0x0003, 0, 0, 0, 0, 2);
 
     assert_eq!(
-        iface.inner.get_source_address_ipv6(&Ipv6Address::LOOPBACK),
-        Ipv6Address::LOOPBACK
+        iface.inner.get_source_address_ipv6(&Ipv6Address::LOCALHOST),
+        Ipv6Address::LOCALHOST
     );
 
     assert_eq!(
@@ -1027,7 +1025,7 @@ fn get_source_address() {
     assert_eq!(
         iface
             .inner
-            .get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES),
+            .get_source_address_ipv6(&IPV6_LINK_LOCAL_ALL_NODES),
         OWN_LINK_LOCAL_ADDR
     );
     assert_eq!(
@@ -1056,7 +1054,7 @@ fn get_source_address() {
         OWN_UNIQUE_LOCAL_ADDR1
     );
     assert_eq!(
-        iface.get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES),
+        iface.get_source_address_ipv6(&IPV6_LINK_LOCAL_ALL_NODES),
         OWN_LINK_LOCAL_ADDR
     );
     assert_eq!(
@@ -1102,8 +1100,8 @@ fn get_source_address_only_link_local() {
         Ipv6Address::new(0x2001, 0x0db9, 0x0003, 0, 0, 0, 0, 2);
 
     assert_eq!(
-        iface.inner.get_source_address_ipv6(&Ipv6Address::LOOPBACK),
-        Ipv6Address::LOOPBACK
+        iface.inner.get_source_address_ipv6(&Ipv6Address::LOCALHOST),
+        Ipv6Address::LOCALHOST
     );
 
     assert_eq!(
@@ -1125,7 +1123,7 @@ fn get_source_address_only_link_local() {
     assert_eq!(
         iface
             .inner
-            .get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES),
+            .get_source_address_ipv6(&IPV6_LINK_LOCAL_ALL_NODES),
         OWN_LINK_LOCAL_ADDR
     );
     assert_eq!(
@@ -1154,7 +1152,7 @@ fn get_source_address_only_link_local() {
         OWN_LINK_LOCAL_ADDR
     );
     assert_eq!(
-        iface.get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES),
+        iface.get_source_address_ipv6(&IPV6_LINK_LOCAL_ALL_NODES),
         OWN_LINK_LOCAL_ADDR
     );
     assert_eq!(
@@ -1193,68 +1191,68 @@ fn get_source_address_empty_interface() {
         Ipv6Address::new(0x2001, 0x0db9, 0x0003, 0, 0, 0, 0, 2);
 
     assert_eq!(
-        iface.inner.get_source_address_ipv6(&Ipv6Address::LOOPBACK),
-        Ipv6Address::LOOPBACK
+        iface.inner.get_source_address_ipv6(&Ipv6Address::LOCALHOST),
+        Ipv6Address::LOCALHOST
     );
 
     assert_eq!(
         iface.inner.get_source_address_ipv6(&LINK_LOCAL_ADDR),
-        Ipv6Address::LOOPBACK
+        Ipv6Address::LOCALHOST
     );
     assert_eq!(
         iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR1),
-        Ipv6Address::LOOPBACK
+        Ipv6Address::LOCALHOST
     );
     assert_eq!(
         iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR2),
-        Ipv6Address::LOOPBACK
+        Ipv6Address::LOCALHOST
     );
     assert_eq!(
         iface.inner.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR3),
-        Ipv6Address::LOOPBACK
+        Ipv6Address::LOCALHOST
     );
     assert_eq!(
         iface
             .inner
-            .get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES),
-        Ipv6Address::LOOPBACK
+            .get_source_address_ipv6(&IPV6_LINK_LOCAL_ALL_NODES),
+        Ipv6Address::LOCALHOST
     );
     assert_eq!(
         iface.inner.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR1),
-        Ipv6Address::LOOPBACK
+        Ipv6Address::LOCALHOST
     );
     assert_eq!(
         iface.inner.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR2),
-        Ipv6Address::LOOPBACK
+        Ipv6Address::LOCALHOST
     );
 
     assert_eq!(
         iface.get_source_address_ipv6(&LINK_LOCAL_ADDR),
-        Ipv6Address::LOOPBACK
+        Ipv6Address::LOCALHOST
     );
     assert_eq!(
         iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR1),
-        Ipv6Address::LOOPBACK
+        Ipv6Address::LOCALHOST
     );
     assert_eq!(
         iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR2),
-        Ipv6Address::LOOPBACK
+        Ipv6Address::LOCALHOST
     );
     assert_eq!(
         iface.get_source_address_ipv6(&UNIQUE_LOCAL_ADDR3),
-        Ipv6Address::LOOPBACK
+        Ipv6Address::LOCALHOST
     );
     assert_eq!(
-        iface.get_source_address_ipv6(&Ipv6Address::LINK_LOCAL_ALL_NODES),
-        Ipv6Address::LOOPBACK
+        iface.get_source_address_ipv6(&IPV6_LINK_LOCAL_ALL_NODES),
+        Ipv6Address::LOCALHOST
     );
     assert_eq!(
         iface.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR1),
-        Ipv6Address::LOOPBACK
+        Ipv6Address::LOCALHOST
     );
     assert_eq!(
         iface.get_source_address_ipv6(&GLOBAL_UNICAST_ADDR2),
-        Ipv6Address::LOOPBACK
+        Ipv6Address::LOCALHOST
     );
 }
 
@@ -1292,8 +1290,8 @@ fn test_join_ipv6_multicast_group(#[case] medium: Medium) {
     let (mut iface, mut sockets, mut device) = setup(medium);
 
     let groups = [
-        Ipv6Address::from_parts(&[0xff05, 0, 0, 0, 0, 0, 0, 0x00fb]),
-        Ipv6Address::from_parts(&[0xff0e, 0, 0, 0, 0, 0, 0, 0x0017]),
+        Ipv6Address::new(0xff05, 0, 0, 0, 0, 0, 0, 0x00fb),
+        Ipv6Address::new(0xff0e, 0, 0, 0, 0, 0, 0, 0x0017),
     ];
 
     let timestamp = Instant::from_millis(0);
@@ -1302,9 +1300,9 @@ fn test_join_ipv6_multicast_group(#[case] medium: Medium) {
         iface.join_multicast_group(group).unwrap();
         assert!(iface.has_multicast_group(group));
     }
-    assert!(iface.has_multicast_group(Ipv6Address::LINK_LOCAL_ALL_NODES));
+    assert!(iface.has_multicast_group(IPV6_LINK_LOCAL_ALL_NODES));
     iface.poll(timestamp, &mut device, &mut sockets);
-    assert!(iface.has_multicast_group(Ipv6Address::LINK_LOCAL_ALL_NODES));
+    assert!(iface.has_multicast_group(IPV6_LINK_LOCAL_ALL_NODES));
 
     let reports = recv_icmpv6(&mut device, timestamp);
     assert_eq!(reports.len(), 2);

+ 1 - 1
src/iface/interface/tests/mod.rs

@@ -98,7 +98,7 @@ fn test_handle_udp_broadcast(#[case] medium: Medium) {
     #[cfg(feature = "proto-ipv6")]
     let ip_repr = IpRepr::Ipv6(Ipv6Repr {
         src_addr: src_ip,
-        dst_addr: Ipv6Address::LINK_LOCAL_ALL_NODES,
+        dst_addr: IPV6_LINK_LOCAL_ALL_NODES,
         next_header: IpProtocol::Udp,
         payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
         hop_limit: 0x40,

+ 17 - 34
src/iface/interface/tests/sixlowpan.rs

@@ -40,8 +40,8 @@ fn icmp_echo_request(#[case] medium: Medium) {
 
     let response = Some(Packet::new_ipv6(
         Ipv6Repr {
-            src_addr: Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0x180b, 0x4242, 0x4242, 0x4242]),
-            dst_addr: Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0x241c, 0x2957, 0x34a6, 0x3a62]),
+            src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0x180b, 0x4242, 0x4242, 0x4242),
+            dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0x241c, 0x2957, 0x34a6, 0x3a62),
             hop_limit: 64,
             next_header: IpProtocol::Icmpv6,
             payload_len: 64,
@@ -61,7 +61,7 @@ fn icmp_echo_request(#[case] medium: Medium) {
     let (mut iface, mut sockets, _device) = setup(medium);
     iface.update_ip_addrs(|ips| {
         ips.push(IpCidr::Ipv6(Ipv6Cidr::new(
-            Ipv6Address::from_parts(&[0xfe80, 0, 0, 0, 0x180b, 0x4242, 0x4242, 0x4242]),
+            Ipv6Address::new(0xfe80, 0, 0, 0, 0x180b, 0x4242, 0x4242, 0x4242),
             10,
         )))
         .unwrap();
@@ -99,7 +99,7 @@ fn test_echo_request_sixlowpan_128_bytes() {
     let now = iface.inner.now();
 
     iface.inner.neighbor_cache.fill(
-        Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0x2, 0, 0, 0, 0, 0, 0, 0]).into(),
+        Ipv6Address::new(0xfe80, 0, 0, 0, 0x0200, 0, 0, 0).into(),
         HardwareAddress::Ieee802154(Ieee802154Address::default()),
         now,
     );
@@ -148,17 +148,11 @@ fn test_echo_request_sixlowpan_128_bytes() {
 
     assert_eq!(
         request_first_part_iphc_repr.src_addr,
-        Ipv6Address([
-            0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42, 0xb,
-            0x1a,
-        ]),
+        Ipv6Address::new(0xfe80, 0, 0, 0, 0x4042, 0x4242, 0x4242, 0x0b1a),
     );
     assert_eq!(
         request_first_part_iphc_repr.dst_addr,
-        Ipv6Address([
-            0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x92, 0xfc, 0x48, 0xc2, 0xa4, 0x41, 0xfc,
-            0x76,
-        ]),
+        Ipv6Address::new(0xfe80, 0, 0, 0, 0x92fc, 0x48c2, 0xa441, 0xfc76),
     );
 
     let request_second_part = [
@@ -206,14 +200,8 @@ fn test_echo_request_sixlowpan_128_bytes() {
         result,
         Some(Packet::new_ipv6(
             Ipv6Repr {
-                src_addr: Ipv6Address([
-                    0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x92, 0xfc, 0x48, 0xc2, 0xa4, 0x41,
-                    0xfc, 0x76,
-                ]),
-                dst_addr: Ipv6Address([
-                    0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42,
-                    0xb, 0x1a,
-                ]),
+                src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0x92fc, 0x48c2, 0xa441, 0xfc76),
+                dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0x4042, 0x4242, 0x4242, 0x0b1a),
                 next_header: IpProtocol::Icmpv6,
                 payload_len: 136,
                 hop_limit: 64,
@@ -227,9 +215,9 @@ fn test_echo_request_sixlowpan_128_bytes() {
     );
 
     iface.inner.neighbor_cache.fill(
-        IpAddress::Ipv6(Ipv6Address([
-            0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42, 0xb, 0x1a,
-        ])),
+        IpAddress::Ipv6(Ipv6Address::new(
+            0xfe80, 0, 0, 0, 0x4042, 0x4242, 0x4242, 0x0b1a,
+        )),
         HardwareAddress::Ieee802154(Ieee802154Address::default()),
         Instant::now(),
     );
@@ -370,17 +358,12 @@ In at rhoncus tortor. Cras blandit tellus diam, varius vestibulum nibh commodo n
             &udp_data[..],
             udp::UdpMetadata {
                 local_address: Some(
-                    Ipv6Address([
-                        0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x92, 0xfc, 0x48, 0xc2, 0xa4,
-                        0x41, 0xfc, 0x76,
-                    ])
-                    .into()
+                    Ipv6Address::new(0xfe80, 0, 0, 0, 0x92fc, 0x48c2, 0xa441, 0xfc76).into()
                 ),
                 ..IpEndpoint {
-                    addr: IpAddress::Ipv6(Ipv6Address([
-                        0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x42, 0x42, 0x42, 0x42,
-                        0x42, 0xb, 0x1a,
-                    ])),
+                    addr: IpAddress::Ipv6(Ipv6Address::new(
+                        0xfe80, 0, 0, 0, 0x4042, 0x4242, 0x4242, 0x0b1a
+                    )),
                     port: 54217,
                 }
                 .into()
@@ -395,8 +378,8 @@ In at rhoncus tortor. Cras blandit tellus diam, varius vestibulum nibh commodo n
         PacketMeta::default(),
         Packet::new_ipv6(
             Ipv6Repr {
-                src_addr: Ipv6Address::default(),
-                dst_addr: Ipv6Address::default(),
+                src_addr: Ipv6Address::UNSPECIFIED,
+                dst_addr: Ipv6Address::UNSPECIFIED,
                 next_header: IpProtocol::Udp,
                 payload_len: udp_data.len(),
                 hop_limit: 64,

+ 7 - 18
src/iface/route.rs

@@ -172,28 +172,17 @@ mod test {
     #[cfg(feature = "proto-ipv6")]
     mod mock {
         use super::super::*;
-        pub const ADDR_1A: Ipv6Address =
-            Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1]);
-        pub const ADDR_1B: Ipv6Address =
-            Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 13]);
-        pub const ADDR_1C: Ipv6Address =
-            Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 42]);
+        pub const ADDR_1A: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 2, 0, 0, 0, 1);
+        pub const ADDR_1B: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 2, 0, 0, 0, 13);
+        pub const ADDR_1C: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 2, 0, 0, 0, 42);
         pub fn cidr_1() -> Ipv6Cidr {
-            Ipv6Cidr::new(
-                Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]),
-                64,
-            )
+            Ipv6Cidr::new(Ipv6Address::new(0xfe80, 0, 0, 2, 0, 0, 0, 0), 64)
         }
 
-        pub const ADDR_2A: Ipv6Address =
-            Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 51, 100, 0, 0, 0, 0, 0, 0, 0, 1]);
-        pub const ADDR_2B: Ipv6Address =
-            Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 51, 100, 0, 0, 0, 0, 0, 0, 0, 21]);
+        pub const ADDR_2A: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0x3364, 0, 0, 0, 1);
+        pub const ADDR_2B: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0x3364, 0, 0, 0, 21);
         pub fn cidr_2() -> Ipv6Cidr {
-            Ipv6Cidr::new(
-                Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 51, 100, 0, 0, 0, 0, 0, 0, 0, 0]),
-                64,
-            )
+            Ipv6Cidr::new(Ipv6Address::new(0xfe80, 0, 0, 0x3364, 0, 0, 0, 0), 64)
         }
     }
 

+ 5 - 6
src/iface/rpl/of0.rs

@@ -99,12 +99,11 @@ mod tests {
         let mut parents = ParentSet::default();
 
         parents.add(
-            Ipv6Address::default(),
-            Parent::new(0, Rank::ROOT, Default::default(), Ipv6Address::default()),
+            Ipv6Address::UNSPECIFIED,
+            Parent::new(0, Rank::ROOT, Default::default(), Ipv6Address::UNSPECIFIED),
         );
 
-        let mut address = Ipv6Address::default();
-        address.0[15] = 1;
+        let address = Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, 1);
 
         parents.add(
             address,
@@ -112,7 +111,7 @@ mod tests {
                 0,
                 Rank::new(1024, DEFAULT_MIN_HOP_RANK_INCREASE),
                 Default::default(),
-                Ipv6Address::default(),
+                Ipv6Address::UNSPECIFIED,
             ),
         );
 
@@ -122,7 +121,7 @@ mod tests {
                 0,
                 Rank::ROOT,
                 Default::default(),
-                Ipv6Address::default(),
+                Ipv6Address::UNSPECIFIED,
             ))
         );
     }

+ 8 - 11
src/iface/rpl/parents.rs

@@ -87,17 +87,17 @@ mod tests {
     fn add_parent() {
         let mut set = ParentSet::default();
         set.add(
-            Default::default(),
-            Parent::new(0, Rank::ROOT, Default::default(), Default::default()),
+            Ipv6Address::UNSPECIFIED,
+            Parent::new(0, Rank::ROOT, Default::default(), Ipv6Address::UNSPECIFIED),
         );
 
         assert_eq!(
-            set.find(&Default::default()),
+            set.find(&Ipv6Address::UNSPECIFIED),
             Some(&Parent::new(
                 0,
                 Rank::ROOT,
                 Default::default(),
-                Default::default()
+                Ipv6Address::UNSPECIFIED
             ))
         );
     }
@@ -107,11 +107,10 @@ mod tests {
         use super::super::consts::DEFAULT_MIN_HOP_RANK_INCREASE;
         let mut set = ParentSet::default();
 
-        let mut last_address = Default::default();
+        let mut last_address = Ipv6Address::UNSPECIFIED;
         for i in 0..RPL_PARENTS_BUFFER_COUNT {
             let i = i as u16;
-            let mut address = Ipv6Address::default();
-            address.0[15] = i as u8;
+            let address = Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, i as _);
             last_address = address;
 
             set.add(
@@ -137,8 +136,7 @@ mod tests {
 
         // This one is not added to the set, because its Rank is worse than any other parent in the
         // set.
-        let mut address = Ipv6Address::default();
-        address.0[15] = 8;
+        let address = Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, 8);
         set.add(
             address,
             Parent::new(
@@ -151,8 +149,7 @@ mod tests {
         assert_eq!(set.find(&address), None);
 
         /// This Parent has a better rank than the last one in the set.
-        let mut address = Ipv6Address::default();
-        address.0[15] = 9;
+        let address = Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, 9);
         set.add(
             address,
             Parent::new(

+ 1 - 5
src/iface/rpl/relations.rs

@@ -73,11 +73,7 @@ mod tests {
 
     fn addresses(count: usize) -> Vec<Ipv6Address> {
         (0..count)
-            .map(|i| {
-                let mut ip = Ipv6Address::default();
-                ip.0[0] = i as u8;
-                ip
-            })
+            .map(|i| Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, i as _))
             .collect()
     }
 

+ 1 - 1
src/macros.rs

@@ -132,7 +132,7 @@ macro_rules! get {
 #[cfg(feature = "proto-rpl")]
 macro_rules! set {
     ($buffer:expr, address: $address:ident, field: $field:expr $(,)?) => {{
-        $buffer.as_mut()[$field].copy_from_slice($address.as_bytes());
+        $buffer.as_mut()[$field].copy_from_slice(&$address.octets());
     }};
 
     ($buffer:expr, $value:ident, field: $field:expr $(,)?) => {

+ 2 - 90
src/parsers.rs

@@ -277,7 +277,7 @@ impl<'a> Parser<'a> {
         // end of the address.
         addr[8 - tail_idx..].copy_from_slice(&tail[..tail_idx]);
 
-        Ok(Ipv6Address::from_parts(&addr))
+        Ok(Ipv6Address::from(addr))
     }
 
     fn accept_ipv4_octets(&mut self) -> Result<[u8; 4]> {
@@ -383,16 +383,6 @@ impl FromStr for EthernetAddress {
     }
 }
 
-#[cfg(feature = "proto-ipv6")]
-impl FromStr for Ipv6Address {
-    type Err = ();
-
-    /// Parse a string representation of an IPv6 address.
-    fn from_str(s: &str) -> Result<Ipv6Address> {
-        Parser::new(s).until_eof(|p| p.accept_ipv6())
-    }
-}
-
 impl FromStr for IpAddress {
     type Err = ();
 
@@ -516,84 +506,6 @@ mod test {
         assert_eq!(EthernetAddress::from_str("02:00:00:00:00:0x"), Err(()));
     }
 
-    #[test]
-    #[cfg(feature = "proto-ipv6")]
-    fn test_ipv6() {
-        // Obviously not valid
-        assert_eq!(Ipv6Address::from_str(""), Err(()));
-        assert_eq!(
-            Ipv6Address::from_str("fe80:0:0:0:0:0:0:1"),
-            Ok(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1))
-        );
-        assert_eq!(Ipv6Address::from_str("::1"), Ok(Ipv6Address::LOOPBACK));
-        assert_eq!(Ipv6Address::from_str("::"), Ok(Ipv6Address::UNSPECIFIED));
-        assert_eq!(
-            Ipv6Address::from_str("fe80::1"),
-            Ok(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1))
-        );
-        assert_eq!(
-            Ipv6Address::from_str("1234:5678::"),
-            Ok(Ipv6Address::new(0x1234, 0x5678, 0, 0, 0, 0, 0, 0))
-        );
-        assert_eq!(
-            Ipv6Address::from_str("1234:5678::8765:4321"),
-            Ok(Ipv6Address::new(0x1234, 0x5678, 0, 0, 0, 0, 0x8765, 0x4321))
-        );
-        // Two double colons in address
-        assert_eq!(Ipv6Address::from_str("1234:5678::1::1"), Err(()));
-        assert_eq!(
-            Ipv6Address::from_str("4444:333:22:1::4"),
-            Ok(Ipv6Address::new(0x4444, 0x0333, 0x0022, 0x0001, 0, 0, 0, 4))
-        );
-        assert_eq!(
-            Ipv6Address::from_str("1:1:1:1:1:1::"),
-            Ok(Ipv6Address::new(1, 1, 1, 1, 1, 1, 0, 0))
-        );
-        assert_eq!(
-            Ipv6Address::from_str("::1:1:1:1:1:1"),
-            Ok(Ipv6Address::new(0, 0, 1, 1, 1, 1, 1, 1))
-        );
-        assert_eq!(Ipv6Address::from_str("::1:1:1:1:1:1:1"), Err(()));
-        // Double colon appears too late indicating an address that is too long
-        assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1::"), Err(()));
-        // Section after double colon is too long for a valid address
-        assert_eq!(Ipv6Address::from_str("::1:1:1:1:1:1:1"), Err(()));
-        // Obviously too long
-        assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1:1:1"), Err(()));
-        // Address is too short
-        assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1"), Err(()));
-        // Long number
-        assert_eq!(Ipv6Address::from_str("::000001"), Err(()));
-        // IPv4-Mapped address
-        assert_eq!(
-            Ipv6Address::from_str("::ffff:192.168.1.1"),
-            Ok(Ipv6Address([
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1
-            ]))
-        );
-        assert_eq!(
-            Ipv6Address::from_str("0:0:0:0:0:ffff:192.168.1.1"),
-            Ok(Ipv6Address([
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1
-            ]))
-        );
-        assert_eq!(
-            Ipv6Address::from_str("0::ffff:192.168.1.1"),
-            Ok(Ipv6Address([
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1
-            ]))
-        );
-        // Only ffff is allowed in position 6 when IPv4 mapped
-        assert_eq!(Ipv6Address::from_str("0:0:0:0:0:eeee:192.168.1.1"), Err(()));
-        // Positions 1-5 must be 0 when IPv4 mapped
-        assert_eq!(Ipv6Address::from_str("0:0:0:0:1:ffff:192.168.1.1"), Err(()));
-        assert_eq!(Ipv6Address::from_str("1::ffff:192.168.1.1"), Err(()));
-        // Out of range ipv4 octet
-        assert_eq!(Ipv6Address::from_str("0:0:0:0:0:ffff:256.168.1.1"), Err(()));
-        // Invalid hex in ipv4 octet
-        assert_eq!(Ipv6Address::from_str("0:0:0:0:0:ffff:c0.168.1.1"), Err(()));
-    }
-
     #[test]
     #[cfg(feature = "proto-ipv4")]
     fn test_ip_ipv4() {
@@ -668,7 +580,7 @@ mod test {
                     64u8,
                 )),
             ),
-            ("::1/128", Ok(Ipv6Cidr::new(Ipv6Address::LOOPBACK, 128u8))),
+            ("::1/128", Ok(Ipv6Cidr::new(Ipv6Address::LOCALHOST, 128u8))),
             ("::/128", Ok(Ipv6Cidr::new(Ipv6Address::UNSPECIFIED, 128u8))),
             (
                 "fe80:0:0:0:0:0:0:1/64",

+ 3 - 3
src/socket/dns.rs

@@ -22,9 +22,9 @@ const RETRANSMIT_TIMEOUT: Duration = Duration::from_millis(10_000); // Should ge
 
 #[cfg(feature = "proto-ipv6")]
 #[allow(unused)]
-const MDNS_IPV6_ADDR: IpAddress = IpAddress::Ipv6(crate::wire::Ipv6Address([
-    0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb,
-]));
+const MDNS_IPV6_ADDR: IpAddress = IpAddress::Ipv6(crate::wire::Ipv6Address::new(
+    0xff02, 0, 0, 0, 0, 0, 0, 0xfb,
+));
 
 #[cfg(feature = "proto-ipv4")]
 #[allow(unused)]

+ 3 - 5
src/socket/icmp.rs

@@ -940,10 +940,8 @@ mod test_ipv6 {
 
     use crate::wire::{Icmpv6DstUnreachable, IpEndpoint, Ipv6Address};
 
-    const REMOTE_IPV6: Ipv6Address =
-        Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
-    const LOCAL_IPV6: Ipv6Address =
-        Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
+    const REMOTE_IPV6: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2);
+    const LOCAL_IPV6: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
     const LOCAL_END_V6: IpEndpoint = IpEndpoint {
         addr: IpAddress::Ipv6(LOCAL_IPV6),
         port: LOCAL_PORT,
@@ -974,7 +972,7 @@ mod test_ipv6 {
     fn test_send_unaddressable() {
         let mut socket = socket(buffer(0), buffer(1));
         assert_eq!(
-            socket.send_slice(b"abcdef", IpAddress::Ipv6(Ipv6Address::default())),
+            socket.send_slice(b"abcdef", IpAddress::Ipv6(Ipv6Address::UNSPECIFIED)),
             Err(SendError::Unaddressable)
         );
         assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV6.into()), Ok(()));

+ 2 - 8
src/socket/raw.rs

@@ -525,14 +525,8 @@ mod test {
 
         pub const IP_PROTO: u8 = 63;
         pub const HEADER_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
-            src_addr: Ipv6Address([
-                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x01,
-            ]),
-            dst_addr: Ipv6Address([
-                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x02,
-            ]),
+            src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
+            dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2),
             next_header: IpProtocol::Unknown(IP_PROTO),
             payload_len: 4,
             hop_limit: 64,

+ 3 - 9
src/socket/tcp.rs

@@ -2615,15 +2615,9 @@ mod test {
             use crate::wire::Ipv6Repr as IpvXRepr;
             use IpRepr::Ipv6 as IpReprIpvX;
 
-            const LOCAL_ADDR: IpvXAddress = IpvXAddress([
-                0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
-            ]);
-            const REMOTE_ADDR: IpvXAddress = IpvXAddress([
-                0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
-            ]);
-            const OTHER_ADDR: IpvXAddress = IpvXAddress([
-                0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
-            ]);
+            const LOCAL_ADDR: IpvXAddress = IpvXAddress::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
+            const REMOTE_ADDR: IpvXAddress = IpvXAddress::new(0xfe80, 0, 0, 0, 0, 0, 0, 2);
+            const OTHER_ADDR: IpvXAddress = IpvXAddress::new(0xfe80, 0, 0, 0, 0, 0, 0, 3);
 
             const BASE_MSS: u16 = 1440;
 

+ 3 - 9
src/socket/udp.rs

@@ -636,15 +636,9 @@ mod test {
             use crate::wire::Ipv6Repr as IpvXRepr;
             use IpRepr::Ipv6 as IpReprIpvX;
 
-            const LOCAL_ADDR: IpvXAddress = IpvXAddress([
-                0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
-            ]);
-            const REMOTE_ADDR: IpvXAddress = IpvXAddress([
-                0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
-            ]);
-            const OTHER_ADDR: IpvXAddress = IpvXAddress([
-                0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
-            ]);
+            const LOCAL_ADDR: IpvXAddress = IpvXAddress::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
+            const REMOTE_ADDR: IpvXAddress = IpvXAddress::new(0xfe80, 0, 0, 0, 0, 0, 0, 2);
+            const OTHER_ADDR: IpvXAddress = IpvXAddress::new(0xfe80, 0, 0, 0, 0, 0, 0, 3);
 
             const LOCAL_END: IpEndpoint = IpEndpoint {
                 addr: IpAddress::Ipv6(LOCAL_ADDR),

+ 2 - 2
src/wire/dns.rs

@@ -6,10 +6,10 @@ use core::iter;
 use core::iter::Iterator;
 
 use super::{Error, Result};
-#[cfg(feature = "proto-ipv6")]
-use crate::wire::Ipv6Address;
 #[cfg(feature = "proto-ipv4")]
 use crate::wire::{Ipv4Address, Ipv4AddressExt};
+#[cfg(feature = "proto-ipv6")]
+use crate::wire::{Ipv6Address, Ipv6AddressExt};
 
 enum_with_unknown! {
     /// DNS OpCodes

+ 8 - 16
src/wire/icmpv6.rs

@@ -847,10 +847,8 @@ mod test {
     use super::*;
     use crate::wire::{IpProtocol, Ipv6Address, Ipv6Repr};
 
-    const MOCK_IP_ADDR_1: Ipv6Address =
-        Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
-    const MOCK_IP_ADDR_2: Ipv6Address =
-        Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
+    const MOCK_IP_ADDR_1: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
+    const MOCK_IP_ADDR_2: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2);
 
     static ECHO_PACKET_BYTES: [u8; 12] = [
         0x80, 0x00, 0x19, 0xb3, 0x12, 0x34, 0xab, 0xcd, 0xaa, 0x00, 0x00, 0xff,
@@ -888,14 +886,8 @@ mod test {
         Repr::PktTooBig {
             mtu: 1500,
             header: Ipv6Repr {
-                src_addr: Ipv6Address([
-                    0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                    0x00, 0x00, 0x01,
-                ]),
-                dst_addr: Ipv6Address([
-                    0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                    0x00, 0x00, 0x02,
-                ]),
+                src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
+                dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2),
                 next_header: IpProtocol::Udp,
                 payload_len: 12,
                 hop_limit: 0x40,
@@ -1017,8 +1009,8 @@ mod test {
         let repr = Repr::PktTooBig {
             mtu: 1280,
             header: Ipv6Repr {
-                src_addr: Default::default(),
-                dst_addr: Default::default(),
+                src_addr: Ipv6Address::UNSPECIFIED,
+                dst_addr: Ipv6Address::UNSPECIFIED,
                 next_header: IpProtocol::Tcp,
                 hop_limit: 64,
                 payload_len: 1280,
@@ -1031,8 +1023,8 @@ mod test {
     #[test]
     fn test_mtu_truncated_payload_roundtrip() {
         let ip_packet_repr = Ipv6Repr {
-            src_addr: Default::default(),
-            dst_addr: Default::default(),
+            src_addr: Ipv6Address::UNSPECIFIED,
+            dst_addr: Ipv6Address::UNSPECIFIED,
             next_header: IpProtocol::Tcp,
             hop_limit: 64,
             payload_len: IPV6_MIN_MTU - IPV6_HEADER_LEN,

+ 1 - 1
src/wire/ieee802154.rs

@@ -3,7 +3,7 @@ use core::fmt;
 use byteorder::{ByteOrder, LittleEndian};
 
 use super::{Error, Result};
-use crate::wire::ipv6::Address as Ipv6Address;
+use crate::wire::{Ipv6Address, Ipv6AddressExt};
 
 enum_with_unknown! {
     /// IEEE 802.15.4 frame type.

+ 8 - 15
src/wire/ip.rs

@@ -6,7 +6,7 @@ use crate::phy::ChecksumCapabilities;
 #[cfg(feature = "proto-ipv4")]
 use crate::wire::{Ipv4Address, Ipv4AddressExt, Ipv4Cidr, Ipv4Packet, Ipv4Repr};
 #[cfg(feature = "proto-ipv6")]
-use crate::wire::{Ipv6Address, Ipv6Cidr, Ipv6Packet, Ipv6Repr};
+use crate::wire::{Ipv6Address, Ipv6AddressExt, Ipv6Cidr, Ipv6Packet, Ipv6Repr};
 
 /// Internet protocol version.
 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
@@ -193,24 +193,17 @@ impl From<Address> for ::core::net::IpAddr {
     fn from(x: Address) -> ::core::net::IpAddr {
         match x {
             #[cfg(feature = "proto-ipv4")]
-            Address::Ipv4(ipv4) => ::core::net::IpAddr::V4(ipv4.into()),
+            Address::Ipv4(ipv4) => ::core::net::IpAddr::V4(ipv4),
             #[cfg(feature = "proto-ipv6")]
-            Address::Ipv6(ipv6) => ::core::net::IpAddr::V6(ipv6.into()),
+            Address::Ipv6(ipv6) => ::core::net::IpAddr::V6(ipv6),
         }
     }
 }
 
 #[cfg(feature = "proto-ipv4")]
-impl From<::core::net::Ipv4Addr> for Address {
-    fn from(ipv4: ::core::net::Ipv4Addr) -> Address {
-        Address::Ipv4(ipv4.into())
-    }
-}
-
-#[cfg(feature = "proto-ipv6")]
-impl From<::core::net::Ipv6Addr> for Address {
-    fn from(ipv6: ::core::net::Ipv6Addr) -> Address {
-        Address::Ipv6(ipv6.into())
+impl From<Ipv4Address> for Address {
+    fn from(ipv4: Ipv4Address) -> Address {
+        Address::Ipv4(ipv4)
     }
 }
 
@@ -759,8 +752,8 @@ pub mod checksum {
         NetworkEndian::write_u16(&mut proto_len[2..4], length as u16);
 
         combine(&[
-            data(src_addr.as_bytes()),
-            data(dst_addr.as_bytes()),
+            data(&src_addr.octets()),
+            data(&dst_addr.octets()),
             data(&proto_len[..]),
         ])
     }

+ 115 - 514
src/wire/ipv6.rs

@@ -5,8 +5,6 @@ use core::fmt;
 
 use super::{Error, Result};
 use crate::wire::ip::pretty_print_ip_payload;
-#[cfg(feature = "proto-ipv4")]
-use crate::wire::{Ipv4Address, Ipv4AddressExt};
 
 pub use super::IpProtocol as Protocol;
 
@@ -20,10 +18,25 @@ pub const MIN_MTU: usize = 1280;
 /// [RFC 8200 § 2]: https://www.rfc-editor.org/rfc/rfc4291#section-2
 pub const ADDR_SIZE: usize = 16;
 
-/// Size of IPv4-mapping prefix in octets.
+/// The link-local [all nodes multicast address].
 ///
-/// [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
+/// [all nodes multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7.1
+pub const LINK_LOCAL_ALL_NODES: Address = Address::new(0xff02, 0, 0, 0, 0, 0, 0, 1);
+
+/// The link-local [all routers multicast address].
+///
+/// [all routers multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7.1
+pub const LINK_LOCAL_ALL_ROUTERS: Address = Address::new(0xff02, 0, 0, 0, 0, 0, 0, 2);
+
+/// The link-local [all MLVDv2-capable routers multicast address].
+///
+/// [all MLVDv2-capable routers multicast address]: https://tools.ietf.org/html/rfc3810#section-11
+pub const LINK_LOCAL_ALL_MLDV2_ROUTERS: Address = Address::new(0xff02, 0, 0, 0, 0, 0, 0, 0x16);
+
+/// The link-local [all RPL nodes multicast address].
+///
+/// [all RPL nodes multicast address]: https://www.rfc-editor.org/rfc/rfc6550.html#section-20.19
+pub const LINK_LOCAL_ALL_RPL_NODES: Address = Address::new(0xff02, 0, 0, 0, 0, 0, 0, 0x1a);
 
 /// The [scope] of an address.
 ///
@@ -61,209 +74,86 @@ impl From<u8> for MulticastScope {
     }
 }
 
-/// A sixteen-octet IPv6 address.
-#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
-pub struct Address(pub [u8; ADDR_SIZE]);
-
-impl Address {
-    /// The [unspecified address].
-    ///
-    /// [unspecified address]: https://tools.ietf.org/html/rfc4291#section-2.5.2
-    pub const UNSPECIFIED: Address = Address([0x00; ADDR_SIZE]);
-
-    /// The link-local [all nodes multicast address].
-    ///
-    /// [all nodes multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7.1
-    pub const LINK_LOCAL_ALL_NODES: Address = Address([
-        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x01,
-    ]);
-
-    /// The link-local [all routers multicast address].
-    ///
-    /// [all routers multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7.1
-    pub const LINK_LOCAL_ALL_ROUTERS: Address = Address([
-        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x02,
-    ]);
-
-    /// The link-local [all MLVDv2-capable routers multicast address].
-    ///
-    /// [all MLVDv2-capable routers multicast address]: https://tools.ietf.org/html/rfc3810#section-11
-    pub const LINK_LOCAL_ALL_MLDV2_ROUTERS: Address = Address([
-        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x16,
-    ]);
-
-    /// The link-local [all RPL nodes multicast address].
-    ///
-    /// [all RPL nodes multicast address]: https://www.rfc-editor.org/rfc/rfc6550.html#section-20.19
-    pub const LINK_LOCAL_ALL_RPL_NODES: Address = Address([
-        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x1a,
-    ]);
-
-    /// The [loopback address].
-    ///
-    /// [loopback address]: https://tools.ietf.org/html/rfc4291#section-2.5.3
-    pub const LOOPBACK: Address = Address([
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x01,
-    ]);
-
-    /// The prefix used in [IPv4-mapped addresses].
-    ///
-    /// [IPv4-mapped addresses]: https://www.rfc-editor.org/rfc/rfc4291#section-2.5.5.2
-    pub const IPV4_MAPPED_PREFIX: [u8; IPV4_MAPPED_PREFIX_SIZE] =
-        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff];
-
-    /// Construct an IPv6 address from parts.
-    #[allow(clippy::too_many_arguments)]
-    pub const fn new(
-        a0: u16,
-        a1: u16,
-        a2: u16,
-        a3: u16,
-        a4: u16,
-        a5: u16,
-        a6: u16,
-        a7: u16,
-    ) -> Address {
-        Address([
-            (a0 >> 8) as u8,
-            a0 as u8,
-            (a1 >> 8) as u8,
-            a1 as u8,
-            (a2 >> 8) as u8,
-            a2 as u8,
-            (a3 >> 8) as u8,
-            a3 as u8,
-            (a4 >> 8) as u8,
-            a4 as u8,
-            (a5 >> 8) as u8,
-            a5 as u8,
-            (a6 >> 8) as u8,
-            a6 as u8,
-            (a7 >> 8) as u8,
-            a7 as u8,
-        ])
-    }
+pub use core::net::Ipv6Addr as Address;
 
+pub(crate) trait AddressExt {
     /// Construct an IPv6 address from a sequence of octets, in big-endian.
     ///
     /// # Panics
     /// The function panics if `data` is not sixteen octets long.
-    pub fn from_bytes(data: &[u8]) -> Address {
-        let mut bytes = [0; ADDR_SIZE];
-        bytes.copy_from_slice(data);
-        Address(bytes)
-    }
-
-    /// Construct an IPv6 address from a sequence of words, in big-endian.
-    ///
-    /// # Panics
-    /// The function panics if `data` is not 8 words long.
-    pub fn from_parts(data: &[u16]) -> Address {
-        assert!(data.len() >= 8);
-        let mut bytes = [0; ADDR_SIZE];
-        for (word_idx, chunk) in bytes.chunks_mut(2).enumerate() {
-            NetworkEndian::write_u16(chunk, data[word_idx]);
-        }
-        Address(bytes)
-    }
-
-    /// Write a IPv6 address to the given slice.
-    ///
-    /// # Panics
-    /// The function panics if `data` is not 8 words long.
-    pub fn write_parts(&self, data: &mut [u16]) {
-        assert!(data.len() >= 8);
-        for (i, chunk) in self.0.chunks(2).enumerate() {
-            data[i] = NetworkEndian::read_u16(chunk);
-        }
-    }
-
-    /// Return an IPv6 address as a sequence of octets, in big-endian.
-    pub const fn as_bytes(&self) -> &[u8] {
-        &self.0
-    }
+    fn from_bytes(data: &[u8]) -> Address;
 
     /// Query whether the IPv6 address is an [unicast address].
     ///
     /// [unicast address]: https://tools.ietf.org/html/rfc4291#section-2.5
-    pub fn is_unicast(&self) -> bool {
-        !(self.is_multicast() || self.is_unspecified())
-    }
+    fn is_unicast(&self) -> bool;
 
     /// 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].
-    ///
-    /// [multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7
-    pub const fn is_multicast(&self) -> bool {
-        self.0[0] == 0xff
-    }
-
-    /// Query whether the IPv6 address is the [unspecified address].
-    ///
-    /// [unspecified address]: https://tools.ietf.org/html/rfc4291#section-2.5.2
-    pub fn is_unspecified(&self) -> bool {
-        self.0 == [0x00; ADDR_SIZE]
-    }
+    fn is_global_unicast(&self) -> bool;
 
     /// Query whether the IPv6 address is in the [link-local] scope.
     ///
     /// [link-local]: https://tools.ietf.org/html/rfc4291#section-2.5.6
-    pub fn is_link_local(&self) -> bool {
-        self.0[0..8] == [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
-    }
+    fn is_link_local(&self) -> bool;
 
     /// Query whether the IPv6 address is a [Unique Local Address] (ULA).
     ///
     /// [Unique Local Address]: https://tools.ietf.org/html/rfc4193
-    pub fn is_unique_local(&self) -> bool {
-        (self.0[0] & 0b1111_1110) == 0xfc
-    }
+    fn is_unique_local(&self) -> bool;
 
-    /// Query whether the IPv6 address is the [loopback address].
+    /// Helper function used to mask an address given a prefix.
     ///
-    /// [loopback address]: https://tools.ietf.org/html/rfc4291#section-2.5.3
-    pub fn is_loopback(&self) -> bool {
-        *self == Self::LOOPBACK
-    }
+    /// # Panics
+    /// This function panics if `mask` is greater than 128.
+    fn mask(&self, mask: u8) -> [u8; ADDR_SIZE];
 
-    /// Query whether the IPv6 address is an [IPv4 mapped IPv6 address].
+    /// The solicited node for the given unicast address.
     ///
-    /// [IPv4 mapped IPv6 address]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
-    pub fn is_ipv4_mapped(&self) -> bool {
-        self.0[..IPV4_MAPPED_PREFIX_SIZE] == Self::IPV4_MAPPED_PREFIX
+    /// # Panics
+    /// This function panics if the given address is not
+    /// unicast.
+    fn solicited_node(&self) -> Address;
+
+    /// Return the scope of the address.
+    fn multicast_scope(&self) -> MulticastScope;
+
+    /// If `self` is a CIDR-compatible subnet mask, return `Some(prefix_len)`,
+    /// where `prefix_len` is the number of leading zeroes. Return `None` otherwise.
+    fn prefix_len(&self) -> Option<u8>;
+}
+
+impl AddressExt for Address {
+    fn from_bytes(data: &[u8]) -> Address {
+        let mut bytes = [0; ADDR_SIZE];
+        bytes.copy_from_slice(data);
+        Address::from(bytes)
     }
 
-    #[cfg(feature = "proto-ipv4")]
-    /// Convert an IPv4 mapped IPv6 address to an IPv4 address.
-    pub fn as_ipv4(&self) -> Option<Ipv4Address> {
-        if self.is_ipv4_mapped() {
-            Some(Ipv4Address::from_bytes(&self.0[IPV4_MAPPED_PREFIX_SIZE..]))
-        } else {
-            None
-        }
+    fn is_unicast(&self) -> bool {
+        !(self.is_multicast() || self.is_unspecified())
     }
 
-    /// Helper function used to mask an address given a prefix.
-    ///
-    /// # Panics
-    /// This function panics if `mask` is greater than 128.
-    pub(super) fn mask(&self, mask: u8) -> [u8; ADDR_SIZE] {
+    fn is_global_unicast(&self) -> bool {
+        (self.octets()[0] >> 5) == 0b001
+    }
+
+    fn is_link_local(&self) -> bool {
+        self.octets()[0..8] == [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+    }
+
+    fn is_unique_local(&self) -> bool {
+        (self.octets()[0] & 0b1111_1110) == 0xfc
+    }
+
+    fn mask(&self, mask: u8) -> [u8; ADDR_SIZE] {
         assert!(mask <= 128);
         let mut bytes = [0u8; ADDR_SIZE];
         let idx = (mask as usize) / 8;
         let modulus = (mask as usize) % 8;
-        let (first, second) = self.0.split_at(idx);
+        let octets = self.octets();
+        let (first, second) = octets.split_at(idx);
         bytes[0..idx].copy_from_slice(first);
         if idx < ADDR_SIZE {
             let part = second[0];
@@ -272,23 +162,18 @@ impl Address {
         bytes
     }
 
-    /// The solicited node for the given unicast address.
-    ///
-    /// # Panics
-    /// This function panics if the given address is not
-    /// unicast.
-    pub fn solicited_node(&self) -> Address {
+    fn solicited_node(&self) -> Address {
         assert!(self.is_unicast());
-        Address([
-            0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF,
-            self.0[13], self.0[14], self.0[15],
+        let o = self.octets();
+        Address::from([
+            0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, o[13],
+            o[14], o[15],
         ])
     }
 
-    /// Return the scope of the address.
-    pub(crate) fn multicast_scope(&self) -> MulticastScope {
+    fn multicast_scope(&self) -> MulticastScope {
         if self.is_multicast() {
-            return MulticastScope::from(self.as_bytes()[1] & 0b1111);
+            return MulticastScope::from(self.octets()[1] & 0b1111);
         }
 
         if self.is_link_local() {
@@ -302,22 +187,13 @@ impl Address {
         }
     }
 
-    /// Convert to an `IpAddress`.
-    ///
-    /// Same as `.into()`, but works in `const`.
-    pub const fn into_address(self) -> super::IpAddress {
-        super::IpAddress::Ipv6(self)
-    }
-
-    /// If `self` is a CIDR-compatible subnet mask, return `Some(prefix_len)`,
-    /// where `prefix_len` is the number of leading zeroes. Return `None` otherwise.
-    pub fn prefix_len(&self) -> Option<u8> {
+    fn prefix_len(&self) -> Option<u8> {
         let mut ones = true;
         let mut prefix_len = 0;
-        for byte in self.as_bytes() {
+        for byte in self.octets() {
             let mut mask = 0x80;
             for _ in 0..8 {
-                let one = *byte & mask != 0;
+                let one = byte & mask != 0;
                 if ones {
                     // Expect 1s until first 0
                     if one {
@@ -336,154 +212,9 @@ impl Address {
     }
 }
 
-impl From<::core::net::Ipv6Addr> for Address {
-    fn from(x: ::core::net::Ipv6Addr) -> Address {
-        Address(x.octets())
-    }
-}
-
-impl From<Address> for ::core::net::Ipv6Addr {
-    fn from(Address(x): Address) -> ::core::net::Ipv6Addr {
-        x.into()
-    }
-}
-
-impl fmt::Display for Address {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if self.is_ipv4_mapped() {
-            return write!(
-                f,
-                "::ffff:{}.{}.{}.{}",
-                self.0[IPV4_MAPPED_PREFIX_SIZE + 0],
-                self.0[IPV4_MAPPED_PREFIX_SIZE + 1],
-                self.0[IPV4_MAPPED_PREFIX_SIZE + 2],
-                self.0[IPV4_MAPPED_PREFIX_SIZE + 3]
-            );
-        }
-
-        // The string representation of an IPv6 address should
-        // collapse a series of 16 bit sections that evaluate
-        // to 0 to "::"
-        //
-        // See https://tools.ietf.org/html/rfc4291#section-2.2
-        // for details.
-        enum State {
-            Head,
-            HeadBody,
-            Tail,
-            TailBody,
-        }
-        let mut words = [0u16; 8];
-        self.write_parts(&mut words);
-        let mut state = State::Head;
-        for word in words.iter() {
-            state = match (*word, &state) {
-                // Once a u16 equal to zero write a double colon and
-                // skip to the next non-zero u16.
-                (0, &State::Head) | (0, &State::HeadBody) => {
-                    write!(f, "::")?;
-                    State::Tail
-                }
-                // Continue iterating without writing any characters until
-                // we hit a non-zero value.
-                (0, &State::Tail) => State::Tail,
-                // When the state is Head or Tail write a u16 in hexadecimal
-                // without the leading colon if the value is not 0.
-                (_, &State::Head) => {
-                    write!(f, "{word:x}")?;
-                    State::HeadBody
-                }
-                (_, &State::Tail) => {
-                    write!(f, "{word:x}")?;
-                    State::TailBody
-                }
-                // Write the u16 with a leading colon when parsing a value
-                // that isn't the first in a section
-                (_, &State::HeadBody) | (_, &State::TailBody) => {
-                    write!(f, ":{word:x}")?;
-                    state
-                }
-            }
-        }
-        Ok(())
-    }
-}
-
-#[cfg(feature = "defmt")]
-impl defmt::Format for Address {
-    fn format(&self, f: defmt::Formatter) {
-        if self.is_ipv4_mapped() {
-            return defmt::write!(
-                f,
-                "::ffff:{}.{}.{}.{}",
-                self.0[IPV4_MAPPED_PREFIX_SIZE + 0],
-                self.0[IPV4_MAPPED_PREFIX_SIZE + 1],
-                self.0[IPV4_MAPPED_PREFIX_SIZE + 2],
-                self.0[IPV4_MAPPED_PREFIX_SIZE + 3]
-            );
-        }
-
-        // The string representation of an IPv6 address should
-        // collapse a series of 16 bit sections that evaluate
-        // to 0 to "::"
-        //
-        // See https://tools.ietf.org/html/rfc4291#section-2.2
-        // for details.
-        enum State {
-            Head,
-            HeadBody,
-            Tail,
-            TailBody,
-        }
-        let mut words = [0u16; 8];
-        self.write_parts(&mut words);
-        let mut state = State::Head;
-        for word in words.iter() {
-            state = match (*word, &state) {
-                // Once a u16 equal to zero write a double colon and
-                // skip to the next non-zero u16.
-                (0, &State::Head) | (0, &State::HeadBody) => {
-                    defmt::write!(f, "::");
-                    State::Tail
-                }
-                // Continue iterating without writing any characters until
-                // we hit a non-zero value.
-                (0, &State::Tail) => State::Tail,
-                // When the state is Head or Tail write a u16 in hexadecimal
-                // without the leading colon if the value is not 0.
-                (_, &State::Head) => {
-                    defmt::write!(f, "{:x}", word);
-                    State::HeadBody
-                }
-                (_, &State::Tail) => {
-                    defmt::write!(f, "{:x}", word);
-                    State::TailBody
-                }
-                // Write the u16 with a leading colon when parsing a value
-                // that isn't the first in a section
-                (_, &State::HeadBody) | (_, &State::TailBody) => {
-                    defmt::write!(f, ":{:x}", word);
-                    state
-                }
-            }
-        }
-    }
-}
-
-#[cfg(feature = "proto-ipv4")]
-/// Convert the given IPv4 address into a IPv4-mapped IPv6 address
-impl From<Ipv4Address> for Address {
-    fn from(address: Ipv4Address) -> Self {
-        let mut b = [0_u8; ADDR_SIZE];
-        b[..Self::IPV4_MAPPED_PREFIX.len()].copy_from_slice(&Self::IPV4_MAPPED_PREFIX);
-        b[Self::IPV4_MAPPED_PREFIX.len()..].copy_from_slice(&address.octets());
-        Self(b)
-    }
-}
-
 /// A specification of an IPv6 CIDR block, containing an address and a variable-length
 /// subnet masking prefix length.
-#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
+#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
 pub struct Cidr {
     address: Address,
     prefix_len: u8,
@@ -494,10 +225,7 @@ impl Cidr {
     ///
     /// [solicited node prefix]: https://tools.ietf.org/html/rfc4291#section-2.7.1
     pub const SOLICITED_NODE_PREFIX: Cidr = Cidr {
-        address: Address([
-            0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00,
-            0x00, 0x00,
-        ]),
+        address: Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0),
         prefix_len: 104,
     };
 
@@ -787,14 +515,14 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     #[inline]
     pub fn set_src_addr(&mut self, value: Address) {
         let data = self.buffer.as_mut();
-        data[field::SRC_ADDR].copy_from_slice(value.as_bytes());
+        data[field::SRC_ADDR].copy_from_slice(&value.octets());
     }
 
     /// Set the destination address field.
     #[inline]
     pub fn set_dst_addr(&mut self, value: Address) {
         let data = self.buffer.as_mut();
-        data[field::DST_ADDR].copy_from_slice(value.as_bytes());
+        data[field::DST_ADDR].copy_from_slice(&value.octets());
     }
 
     /// Return a mutable pointer to the payload.
@@ -928,26 +656,17 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
 
 #[cfg(test)]
 pub(crate) mod test {
-    use super::Error;
-    use super::{Address, Cidr};
-    use super::{Packet, Protocol, Repr};
+    use super::*;
     use crate::wire::pretty_print::PrettyPrinter;
 
-    #[cfg(feature = "proto-ipv4")]
-    use crate::wire::ipv4::Address as Ipv4Address;
-
     #[allow(unused)]
-    pub(crate) const MOCK_IP_ADDR_1: Address =
-        Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
+    pub(crate) const MOCK_IP_ADDR_1: Address = Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
     #[allow(unused)]
-    pub(crate) const MOCK_IP_ADDR_2: Address =
-        Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
+    pub(crate) const MOCK_IP_ADDR_2: Address = Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2);
     #[allow(unused)]
-    pub(crate) const MOCK_IP_ADDR_3: Address =
-        Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]);
+    pub(crate) const MOCK_IP_ADDR_3: Address = Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 3);
     #[allow(unused)]
-    pub(crate) const MOCK_IP_ADDR_4: Address =
-        Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4]);
+    pub(crate) const MOCK_IP_ADDR_4: Address = Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 4);
     #[allow(unused)]
     pub(crate) const MOCK_UNSPECIFIED: Address = Address::UNSPECIFIED;
 
@@ -957,18 +676,18 @@ pub(crate) mod test {
 
     #[test]
     fn test_basic_multicast() {
-        assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_unspecified());
-        assert!(Address::LINK_LOCAL_ALL_ROUTERS.is_multicast());
-        assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_link_local());
-        assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_loopback());
-        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_multicast());
-        assert!(!Address::LINK_LOCAL_ALL_NODES.is_link_local());
-        assert!(!Address::LINK_LOCAL_ALL_NODES.is_loopback());
-        assert!(!Address::LINK_LOCAL_ALL_NODES.is_unique_local());
-        assert!(!Address::LINK_LOCAL_ALL_NODES.is_global_unicast());
+        assert!(!LINK_LOCAL_ALL_ROUTERS.is_unspecified());
+        assert!(LINK_LOCAL_ALL_ROUTERS.is_multicast());
+        assert!(!LINK_LOCAL_ALL_ROUTERS.is_link_local());
+        assert!(!LINK_LOCAL_ALL_ROUTERS.is_loopback());
+        assert!(!LINK_LOCAL_ALL_ROUTERS.is_unique_local());
+        assert!(!LINK_LOCAL_ALL_ROUTERS.is_global_unicast());
+        assert!(!LINK_LOCAL_ALL_NODES.is_unspecified());
+        assert!(LINK_LOCAL_ALL_NODES.is_multicast());
+        assert!(!LINK_LOCAL_ALL_NODES.is_link_local());
+        assert!(!LINK_LOCAL_ALL_NODES.is_loopback());
+        assert!(!LINK_LOCAL_ALL_NODES.is_unique_local());
+        assert!(!LINK_LOCAL_ALL_NODES.is_global_unicast());
     }
 
     #[test]
@@ -983,12 +702,12 @@ pub(crate) mod test {
 
     #[test]
     fn test_basic_loopback() {
-        assert!(!Address::LOOPBACK.is_unspecified());
-        assert!(!Address::LOOPBACK.is_multicast());
-        assert!(!Address::LOOPBACK.is_link_local());
-        assert!(Address::LOOPBACK.is_loopback());
-        assert!(!Address::LOOPBACK.is_unique_local());
-        assert!(!Address::LOOPBACK.is_global_unicast());
+        assert!(!Address::LOCALHOST.is_unspecified());
+        assert!(!Address::LOCALHOST.is_multicast());
+        assert!(!Address::LOCALHOST.is_link_local());
+        assert!(Address::LOCALHOST.is_loopback());
+        assert!(!Address::LOCALHOST.is_unique_local());
+        assert!(!Address::LOCALHOST.is_global_unicast());
     }
 
     #[test]
@@ -1011,83 +730,6 @@ pub(crate) mod test {
         assert!(GLOBAL_UNICAST_ADDR.is_global_unicast());
     }
 
-    #[test]
-    fn test_address_format() {
-        assert_eq!("ff02::1", format!("{}", Address::LINK_LOCAL_ALL_NODES));
-        assert_eq!("fe80::1", format!("{LINK_LOCAL_ADDR}"));
-        assert_eq!(
-            "fe80::7f00:0:1",
-            format!(
-                "{}",
-                Address::new(0xfe80, 0, 0, 0, 0, 0x7f00, 0x0000, 0x0001)
-            )
-        );
-        assert_eq!("::", format!("{}", Address::UNSPECIFIED));
-        assert_eq!("::1", format!("{}", Address::LOOPBACK));
-
-        #[cfg(feature = "proto-ipv4")]
-        assert_eq!(
-            "::ffff:192.168.1.1",
-            format!("{}", Address::from(Ipv4Address::new(192, 168, 1, 1)))
-        );
-    }
-
-    #[test]
-    fn test_new() {
-        assert_eq!(
-            Address::new(0xff02, 0, 0, 0, 0, 0, 0, 1),
-            Address::LINK_LOCAL_ALL_NODES
-        );
-        assert_eq!(
-            Address::new(0xff02, 0, 0, 0, 0, 0, 0, 2),
-            Address::LINK_LOCAL_ALL_ROUTERS
-        );
-        assert_eq!(Address::new(0, 0, 0, 0, 0, 0, 0, 1), Address::LOOPBACK);
-        assert_eq!(Address::new(0, 0, 0, 0, 0, 0, 0, 0), Address::UNSPECIFIED);
-        assert_eq!(Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), LINK_LOCAL_ADDR);
-    }
-
-    #[test]
-    fn test_from_parts() {
-        assert_eq!(
-            Address::from_parts(&[0xff02, 0, 0, 0, 0, 0, 0, 1]),
-            Address::LINK_LOCAL_ALL_NODES
-        );
-        assert_eq!(
-            Address::from_parts(&[0xff02, 0, 0, 0, 0, 0, 0, 2]),
-            Address::LINK_LOCAL_ALL_ROUTERS
-        );
-        assert_eq!(
-            Address::from_parts(&[0, 0, 0, 0, 0, 0, 0, 1]),
-            Address::LOOPBACK
-        );
-        assert_eq!(
-            Address::from_parts(&[0, 0, 0, 0, 0, 0, 0, 0]),
-            Address::UNSPECIFIED
-        );
-        assert_eq!(
-            Address::from_parts(&[0xfe80, 0, 0, 0, 0, 0, 0, 1]),
-            LINK_LOCAL_ADDR
-        );
-    }
-
-    #[test]
-    fn test_write_parts() {
-        let mut bytes = [0u16; 8];
-        {
-            Address::LOOPBACK.write_parts(&mut bytes);
-            assert_eq!(Address::LOOPBACK, Address::from_parts(&bytes));
-        }
-        {
-            Address::LINK_LOCAL_ALL_ROUTERS.write_parts(&mut bytes);
-            assert_eq!(Address::LINK_LOCAL_ALL_ROUTERS, Address::from_parts(&bytes));
-        }
-        {
-            LINK_LOCAL_ADDR.write_parts(&mut bytes);
-            assert_eq!(LINK_LOCAL_ADDR, Address::from_parts(&bytes));
-        }
-    }
-
     #[test]
     fn test_mask() {
         let addr = Address::new(0x0123, 0x4567, 0x89ab, 0, 0, 0, 0, 1);
@@ -1113,35 +755,6 @@ pub(crate) mod test {
         );
     }
 
-    #[cfg(feature = "proto-ipv4")]
-    #[test]
-    fn test_is_ipv4_mapped() {
-        assert!(!Address::UNSPECIFIED.is_ipv4_mapped());
-        assert!(Address::from(Ipv4Address::new(192, 168, 1, 1)).is_ipv4_mapped());
-    }
-
-    #[cfg(feature = "proto-ipv4")]
-    #[test]
-    fn test_as_ipv4() {
-        assert_eq!(None, Address::UNSPECIFIED.as_ipv4());
-
-        let ipv4 = Ipv4Address::new(192, 168, 1, 1);
-        assert_eq!(Some(ipv4), Address::from(ipv4).as_ipv4());
-    }
-
-    #[cfg(feature = "proto-ipv4")]
-    #[test]
-    fn test_from_ipv4_address() {
-        assert_eq!(
-            Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1]),
-            Address::from(Ipv4Address::new(192, 168, 1, 1))
-        );
-        assert_eq!(
-            Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 222, 1, 41, 90]),
-            Address::from(Ipv4Address::new(222, 1, 41, 90))
-        );
-    }
-
     #[test]
     fn test_cidr() {
         // fe80::1/56
@@ -1265,16 +878,19 @@ pub(crate) mod test {
             assert!(!cidr.contains_addr(&addr));
         }
 
-        for subnet in subnets.iter().map(|&(a, p)| Cidr::new(Address(a), p)) {
+        for subnet in subnets.iter().map(|&(a, p)| Cidr::new(Address::from(a), p)) {
             assert!(cidr.contains_subnet(&subnet));
         }
 
-        for subnet in not_subnets.iter().map(|&(a, p)| Cidr::new(Address(a), p)) {
+        for subnet in not_subnets
+            .iter()
+            .map(|&(a, p)| Cidr::new(Address::from(a), p))
+        {
             assert!(!cidr.contains_subnet(&subnet));
         }
 
         let cidr_without_prefix = Cidr::new(LINK_LOCAL_ADDR, 0);
-        assert!(cidr_without_prefix.contains_addr(&Address::LOOPBACK));
+        assert!(cidr_without_prefix.contains_addr(&Address::LOCALHOST));
     }
 
     #[test]
@@ -1283,12 +899,6 @@ pub(crate) mod test {
         let _ = Address::from_bytes(&[0u8; 15]);
     }
 
-    #[test]
-    #[should_panic(expected = "data.len() >= 8")]
-    fn test_from_parts_too_long() {
-        let _ = Address::from_parts(&[0u16; 7]);
-    }
-
     #[test]
     fn test_scope() {
         use super::*;
@@ -1322,7 +932,7 @@ pub(crate) mod test {
         );
 
         assert_eq!(
-            Address::LINK_LOCAL_ALL_NODES.multicast_scope(),
+            LINK_LOCAL_ALL_NODES.multicast_scope(),
             MulticastScope::LinkLocal
         );
 
@@ -1347,11 +957,8 @@ pub(crate) mod test {
 
     const fn packet_repr() -> Repr {
         Repr {
-            src_addr: Address([
-                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x01,
-            ]),
-            dst_addr: Address::LINK_LOCAL_ALL_NODES,
+            src_addr: Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
+            dst_addr: LINK_LOCAL_ALL_NODES,
             next_header: Protocol::Udp,
             payload_len: 12,
             hop_limit: 64,
@@ -1369,14 +976,8 @@ pub(crate) mod test {
         assert_eq!(packet.payload_len() as usize, REPR_PAYLOAD_BYTES.len());
         assert_eq!(packet.next_header(), Protocol::Udp);
         assert_eq!(packet.hop_limit(), 0x40);
-        assert_eq!(
-            packet.src_addr(),
-            Address([
-                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x01
-            ])
-        );
-        assert_eq!(packet.dst_addr(), Address::LINK_LOCAL_ALL_NODES);
+        assert_eq!(packet.src_addr(), Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1));
+        assert_eq!(packet.dst_addr(), LINK_LOCAL_ALL_NODES);
         assert_eq!(packet.payload(), &REPR_PAYLOAD_BYTES[..]);
     }
 
@@ -1398,8 +999,8 @@ pub(crate) mod test {
         packet.set_payload_len(0xc);
         packet.set_next_header(Protocol::Udp);
         packet.set_hop_limit(0xfe);
-        packet.set_src_addr(Address::LINK_LOCAL_ALL_ROUTERS);
-        packet.set_dst_addr(Address::LINK_LOCAL_ALL_NODES);
+        packet.set_src_addr(LINK_LOCAL_ALL_ROUTERS);
+        packet.set_dst_addr(LINK_LOCAL_ALL_NODES);
         packet
             .payload_mut()
             .copy_from_slice(&REPR_PAYLOAD_BYTES[..]);

+ 5 - 5
src/wire/ipv6routing.rs

@@ -1,7 +1,7 @@
 use super::{Error, Result};
 use core::fmt;
 
-use crate::wire::Ipv6Address as Address;
+use crate::wire::{Ipv6Address as Address, Ipv6AddressExt};
 
 enum_with_unknown! {
     /// IPv6 Extension Routing Header Routing Type
@@ -286,7 +286,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Header<T> {
     /// This function may panic if this header is not the Type 2 Routing Header routing type.
     pub fn set_home_address(&mut self, value: Address) {
         let data = self.buffer.as_mut();
-        data[field::HOME_ADDRESS].copy_from_slice(value.as_bytes());
+        data[field::HOME_ADDRESS].copy_from_slice(&value.octets());
     }
 }
 
@@ -399,7 +399,7 @@ impl<'a> Repr<'a> {
     pub const fn buffer_len(&self) -> usize {
         match self {
             // Routing Type + Segments Left + Reserved + Home Address
-            Repr::Type2 { home_address, .. } => 2 + 4 + home_address.as_bytes().len(),
+            Repr::Type2 { home_address, .. } => 2 + 4 + home_address.octets().len(),
             Repr::Rpl { addresses, .. } => 2 + 4 + addresses.len(),
         }
     }
@@ -484,7 +484,7 @@ mod test {
     // A representation of a Type 2 Routing header
     static REPR_TYPE2: Repr = Repr::Type2 {
         segments_left: 1,
-        home_address: Address::LOOPBACK,
+        home_address: Address::LOCALHOST,
     };
 
     // A Source Routing Header with full IPv6 addresses in bytes
@@ -552,7 +552,7 @@ mod test {
         let header = Header::new_unchecked(&BYTES_TYPE2[..]);
         assert_eq!(header.routing_type(), Type::Type2);
         assert_eq!(header.segments_left(), 1);
-        assert_eq!(header.home_address(), Address::LOOPBACK);
+        assert_eq!(header.home_address(), Address::LOCALHOST);
 
         let header = Header::new_unchecked(&BYTES_SRH_FULL[..]);
         assert_eq!(header.routing_type(), Type::Rpl);

+ 23 - 29
src/wire/mld.rs

@@ -8,7 +8,7 @@ use byteorder::{ByteOrder, NetworkEndian};
 
 use super::{Error, Result};
 use crate::wire::icmpv6::{field, Message, Packet};
-use crate::wire::Ipv6Address;
+use crate::wire::{Ipv6Address, Ipv6AddressExt};
 
 enum_with_unknown! {
     /// MLDv2 Multicast Listener Report Record Type. See [RFC 3810 § 5.2.12] for
@@ -110,7 +110,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     #[inline]
     pub fn set_mcast_addr(&mut self, addr: Ipv6Address) {
         let data = self.buffer.as_mut();
-        data[field::QUERY_MCAST_ADDR].copy_from_slice(addr.as_bytes());
+        data[field::QUERY_MCAST_ADDR].copy_from_slice(&addr.octets());
     }
 
     /// Set the Suppress Router-Side Processing flag.
@@ -281,7 +281,7 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>> AddressRecord<T> {
     pub fn set_mcast_addr(&mut self, addr: Ipv6Address) {
         assert!(addr.is_multicast());
         let data = self.buffer.as_mut();
-        data[field::RECORD_MCAST_ADDR].copy_from_slice(addr.as_bytes());
+        data[field::RECORD_MCAST_ADDR].copy_from_slice(&addr.octets());
     }
 }
 
@@ -460,7 +460,7 @@ mod test {
     use super::*;
     use crate::phy::ChecksumCapabilities;
     use crate::wire::icmpv6::Message;
-    use crate::wire::Icmpv6Repr;
+    use crate::wire::{Icmpv6Repr, IPV6_LINK_LOCAL_ALL_NODES, IPV6_LINK_LOCAL_ALL_ROUTERS};
 
     static QUERY_PACKET_BYTES: [u8; 44] = [
         0x82, 0x00, 0x73, 0x74, 0x04, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -489,7 +489,7 @@ mod test {
         match ty {
             Message::MldQuery => Icmpv6Repr::Mld(Repr::Query {
                 max_resp_code: 0x400,
-                mcast_addr: Ipv6Address::LINK_LOCAL_ALL_NODES,
+                mcast_addr: IPV6_LINK_LOCAL_ALL_NODES,
                 s_flag: true,
                 qrv: 0x02,
                 qqic: 0x12,
@@ -513,14 +513,14 @@ mod test {
         assert_eq!(packet.msg_code(), 0);
         assert_eq!(packet.checksum(), 0x7374);
         assert_eq!(packet.max_resp_code(), 0x0400);
-        assert_eq!(packet.mcast_addr(), Ipv6Address::LINK_LOCAL_ALL_NODES);
+        assert_eq!(packet.mcast_addr(), IPV6_LINK_LOCAL_ALL_NODES);
         assert!(packet.s_flag());
         assert_eq!(packet.qrv(), 0x02);
         assert_eq!(packet.qqic(), 0x12);
         assert_eq!(packet.num_srcs(), 0x01);
         assert_eq!(
             Ipv6Address::from_bytes(packet.payload()),
-            Ipv6Address::LINK_LOCAL_ALL_ROUTERS
+            IPV6_LINK_LOCAL_ALL_ROUTERS
         );
     }
 
@@ -531,19 +531,16 @@ mod test {
         packet.set_msg_type(Message::MldQuery);
         packet.set_msg_code(0);
         packet.set_max_resp_code(0x0400);
-        packet.set_mcast_addr(Ipv6Address::LINK_LOCAL_ALL_NODES);
+        packet.set_mcast_addr(IPV6_LINK_LOCAL_ALL_NODES);
         packet.set_s_flag();
         packet.set_qrv(0x02);
         packet.set_qqic(0x12);
         packet.set_num_srcs(0x01);
         packet
             .payload_mut()
-            .copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes());
+            .copy_from_slice(&IPV6_LINK_LOCAL_ALL_ROUTERS.octets());
         packet.clear_reserved();
-        packet.fill_checksum(
-            &Ipv6Address::LINK_LOCAL_ALL_NODES,
-            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
-        );
+        packet.fill_checksum(&IPV6_LINK_LOCAL_ALL_NODES, &IPV6_LINK_LOCAL_ALL_ROUTERS);
         assert_eq!(&*packet.into_inner(), &QUERY_PACKET_BYTES[..]);
     }
 
@@ -558,10 +555,10 @@ mod test {
         assert_eq!(addr_rcrd.record_type(), RecordType::ModeIsInclude);
         assert_eq!(addr_rcrd.aux_data_len(), 0x00);
         assert_eq!(addr_rcrd.num_srcs(), 0x01);
-        assert_eq!(addr_rcrd.mcast_addr(), Ipv6Address::LINK_LOCAL_ALL_NODES);
+        assert_eq!(addr_rcrd.mcast_addr(), IPV6_LINK_LOCAL_ALL_NODES);
         assert_eq!(
             Ipv6Address::from_bytes(addr_rcrd.payload()),
-            Ipv6Address::LINK_LOCAL_ALL_ROUTERS
+            IPV6_LINK_LOCAL_ALL_ROUTERS
         );
     }
 
@@ -578,15 +575,12 @@ mod test {
             addr_rcrd.set_record_type(RecordType::ModeIsInclude);
             addr_rcrd.set_aux_data_len(0);
             addr_rcrd.set_num_srcs(1);
-            addr_rcrd.set_mcast_addr(Ipv6Address::LINK_LOCAL_ALL_NODES);
+            addr_rcrd.set_mcast_addr(IPV6_LINK_LOCAL_ALL_NODES);
             addr_rcrd
                 .payload_mut()
-                .copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes());
+                .copy_from_slice(&IPV6_LINK_LOCAL_ALL_ROUTERS.octets());
         }
-        packet.fill_checksum(
-            &Ipv6Address::LINK_LOCAL_ALL_NODES,
-            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
-        );
+        packet.fill_checksum(&IPV6_LINK_LOCAL_ALL_NODES, &IPV6_LINK_LOCAL_ALL_ROUTERS);
         assert_eq!(&*packet.into_inner(), &REPORT_PACKET_BYTES[..]);
     }
 
@@ -594,8 +588,8 @@ mod test {
     fn test_query_repr_parse() {
         let packet = Packet::new_unchecked(&QUERY_PACKET_BYTES[..]);
         let repr = Icmpv6Repr::parse(
-            &Ipv6Address::LINK_LOCAL_ALL_NODES,
-            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
+            &IPV6_LINK_LOCAL_ALL_NODES,
+            &IPV6_LINK_LOCAL_ALL_ROUTERS,
             &packet,
             &ChecksumCapabilities::default(),
         );
@@ -606,8 +600,8 @@ mod test {
     fn test_report_repr_parse() {
         let packet = Packet::new_unchecked(&REPORT_PACKET_BYTES[..]);
         let repr = Icmpv6Repr::parse(
-            &Ipv6Address::LINK_LOCAL_ALL_NODES,
-            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
+            &IPV6_LINK_LOCAL_ALL_NODES,
+            &IPV6_LINK_LOCAL_ALL_ROUTERS,
             &packet,
             &ChecksumCapabilities::default(),
         );
@@ -620,8 +614,8 @@ mod test {
         let mut packet = Packet::new_unchecked(&mut bytes[..]);
         let repr = create_repr(Message::MldQuery);
         repr.emit(
-            &Ipv6Address::LINK_LOCAL_ALL_NODES,
-            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
+            &IPV6_LINK_LOCAL_ALL_NODES,
+            &IPV6_LINK_LOCAL_ALL_ROUTERS,
             &mut packet,
             &ChecksumCapabilities::default(),
         );
@@ -634,8 +628,8 @@ mod test {
         let mut packet = Packet::new_unchecked(&mut bytes[..]);
         let repr = create_repr(Message::MldReport);
         repr.emit(
-            &Ipv6Address::LINK_LOCAL_ALL_NODES,
-            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS,
+            &IPV6_LINK_LOCAL_ALL_NODES,
+            &IPV6_LINK_LOCAL_ALL_ROUTERS,
             &mut packet,
             &ChecksumCapabilities::default(),
         );

+ 7 - 3
src/wire/mod.rs

@@ -195,13 +195,17 @@ pub use self::ipv4::{
 #[cfg(feature = "proto-ipv4")]
 pub(crate) use self::ipv4::AddressExt as Ipv4AddressExt;
 
-#[cfg(feature = "proto-ipv6")]
-pub(crate) use self::ipv6::MulticastScope as Ipv6MulticastScope;
 #[cfg(feature = "proto-ipv6")]
 pub use self::ipv6::{
     Address as Ipv6Address, Cidr as Ipv6Cidr, Packet as Ipv6Packet, Repr as Ipv6Repr,
-    HEADER_LEN as IPV6_HEADER_LEN, MIN_MTU as IPV6_MIN_MTU,
+    HEADER_LEN as IPV6_HEADER_LEN,
+    LINK_LOCAL_ALL_MLDV2_ROUTERS as IPV6_LINK_LOCAL_ALL_MLDV2_ROUTERS,
+    LINK_LOCAL_ALL_NODES as IPV6_LINK_LOCAL_ALL_NODES,
+    LINK_LOCAL_ALL_ROUTERS as IPV6_LINK_LOCAL_ALL_ROUTERS,
+    LINK_LOCAL_ALL_RPL_NODES as IPV6_LINK_LOCAL_ALL_RPL_NODES, MIN_MTU as IPV6_MIN_MTU,
 };
+#[cfg(feature = "proto-ipv6")]
+pub(crate) use self::ipv6::{AddressExt as Ipv6AddressExt, MulticastScope as Ipv6MulticastScope};
 
 #[cfg(feature = "proto-ipv6")]
 pub use self::ipv6option::{

+ 5 - 7
src/wire/ndisc.rs

@@ -4,8 +4,8 @@ use byteorder::{ByteOrder, NetworkEndian};
 use super::{Error, Result};
 use crate::time::Duration;
 use crate::wire::icmpv6::{field, Message, Packet};
-use crate::wire::Ipv6Address;
 use crate::wire::RawHardwareAddress;
+use crate::wire::{Ipv6Address, Ipv6AddressExt};
 use crate::wire::{NdiscOption, NdiscOptionRepr};
 use crate::wire::{NdiscPrefixInformation, NdiscRedirectedHeader};
 
@@ -159,7 +159,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     #[inline]
     pub fn set_target_addr(&mut self, value: Ipv6Address) {
         let data = self.buffer.as_mut();
-        data[field::TARGET_ADDR].copy_from_slice(value.as_bytes());
+        data[field::TARGET_ADDR].copy_from_slice(&value.octets());
     }
 }
 
@@ -184,7 +184,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     #[inline]
     pub fn set_dest_addr(&mut self, value: Ipv6Address) {
         let data = self.buffer.as_mut();
-        data[field::DEST_ADDR].copy_from_slice(value.as_bytes());
+        data[field::DEST_ADDR].copy_from_slice(&value.octets());
     }
 }
 
@@ -462,10 +462,8 @@ mod test {
     use crate::wire::EthernetAddress;
     use crate::wire::Icmpv6Repr;
 
-    const MOCK_IP_ADDR_1: Ipv6Address =
-        Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
-    const MOCK_IP_ADDR_2: Ipv6Address =
-        Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
+    const MOCK_IP_ADDR_1: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
+    const MOCK_IP_ADDR_2: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2);
 
     static ROUTER_ADVERT_BYTES: [u8; 24] = [
         0x86, 0x00, 0xa9, 0xde, 0x40, 0x80, 0x03, 0x84, 0x00, 0x00, 0x03, 0x84, 0x00, 0x00, 0x03,

+ 2 - 2
src/wire/ndiscoption.rs

@@ -4,7 +4,7 @@ use core::fmt;
 
 use super::{Error, Result};
 use crate::time::Duration;
-use crate::wire::{Ipv6Address, Ipv6Packet, Ipv6Repr, MAX_HARDWARE_ADDRESS_LEN};
+use crate::wire::{Ipv6Address, Ipv6AddressExt, Ipv6Packet, Ipv6Repr, MAX_HARDWARE_ADDRESS_LEN};
 
 use crate::wire::RawHardwareAddress;
 
@@ -356,7 +356,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> NdiscOption<T> {
     #[inline]
     pub fn set_prefix(&mut self, addr: Ipv6Address) {
         let data = self.buffer.as_mut();
-        data[field::PREFIX].copy_from_slice(addr.as_bytes());
+        data[field::PREFIX].copy_from_slice(&addr.octets());
     }
 }
 

+ 9 - 11
src/wire/rpl.rs

@@ -6,7 +6,7 @@ use byteorder::{ByteOrder, NetworkEndian};
 
 use super::{Error, Result};
 use crate::wire::icmpv6::Packet;
-use crate::wire::ipv6::Address;
+use crate::wire::ipv6::{Address, AddressExt};
 
 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -508,7 +508,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     pub fn set_dao_dodag_id(&mut self, address: Option<Address>) {
         match address {
             Some(address) => {
-                self.buffer.as_mut()[field::DAO_DODAG_ID].copy_from_slice(address.as_bytes());
+                self.buffer.as_mut()[field::DAO_DODAG_ID].copy_from_slice(&address.octets());
                 self.set_dao_dodag_id_present(true);
             }
             None => {
@@ -594,7 +594,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     pub fn set_dao_ack_dodag_id(&mut self, address: Option<Address>) {
         match address {
             Some(address) => {
-                self.buffer.as_mut()[field::DAO_ACK_DODAG_ID].copy_from_slice(address.as_bytes());
+                self.buffer.as_mut()[field::DAO_ACK_DODAG_ID].copy_from_slice(&address.octets());
                 self.set_dao_ack_dodag_id_present(true);
             }
             None => {
@@ -866,7 +866,7 @@ pub mod options {
     use byteorder::{ByteOrder, NetworkEndian};
 
     use super::{Error, InstanceId, Result};
-    use crate::wire::ipv6::Address;
+    use crate::wire::ipv6::{Address, AddressExt};
 
     /// A read/write wrapper around a RPL Control Message Option.
     #[derive(Debug, Clone)]
@@ -1497,7 +1497,7 @@ pub mod options {
         #[inline]
         pub fn set_transit_info_parent_address(&mut self, address: Address) {
             self.buffer.as_mut()[field::TRANSIT_INFO_PARENT_ADDRESS]
-                .copy_from_slice(address.as_bytes());
+                .copy_from_slice(&address.octets());
         }
     }
 
@@ -2095,7 +2095,7 @@ pub mod options {
                 Repr::DagMetricContainer => todo!(),
                 Repr::RouteInformation { prefix, .. } => 2 + 6 + prefix.len(),
                 Repr::DodagConfiguration { .. } => 2 + 14,
-                Repr::RplTarget { prefix, .. } => 2 + 2 + prefix.0.len(),
+                Repr::RplTarget { prefix, .. } => 2 + 2 + prefix.octets().len(),
                 Repr::TransitInformation { parent_address, .. } => {
                     2 + 4 + if parent_address.is_some() { 16 } else { 0 }
                 }
@@ -2165,7 +2165,7 @@ pub mod options {
                 } => {
                     packet.clear_rpl_target_flags();
                     packet.set_rpl_target_prefix_length(*prefix_length);
-                    packet.set_rpl_target_prefix(prefix.as_bytes());
+                    packet.set_rpl_target_prefix(&prefix.octets());
                 }
                 Repr::TransitInformation {
                     external,
@@ -2616,7 +2616,7 @@ mod tests {
                 prefix,
             } => {
                 assert_eq!(prefix_length, 128);
-                assert_eq!(prefix.as_bytes(), &target_prefix[..]);
+                assert_eq!(prefix.octets(), target_prefix);
             }
             _ => unreachable!(),
         }
@@ -2707,9 +2707,7 @@ mod tests {
                 assert_eq!(status, 0x0);
                 assert_eq!(
                     dodag_id,
-                    Some(Ipv6Address([
-                        254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1
-                    ]))
+                    Some(Ipv6Address::new(0xfe80, 0, 0, 0, 0x0200, 0, 0, 1))
                 );
             }
             _ => unreachable!(),

+ 8 - 8
src/wire/sixlowpan/iphc.rs

@@ -6,7 +6,7 @@
 use super::{
     AddressContext, AddressMode, Error, NextHeader, Result, UnresolvedAddress, DISPATCH_IPHC_HEADER,
 };
-use crate::wire::{ieee802154::Address as LlAddress, ipv6, IpProtocol};
+use crate::wire::{ieee802154::Address as LlAddress, ipv6, ipv6::AddressExt, IpProtocol};
 use byteorder::{ByteOrder, NetworkEndian};
 
 mod field {
@@ -526,7 +526,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     ) -> usize {
         self.set_cid_field(0);
         self.set_sac_field(0);
-        let src = src_addr.as_bytes();
+        let src = src_addr.octets();
         if src_addr == ipv6::Address::UNSPECIFIED {
             self.set_sac_field(1);
             self.set_sam_field(0b00);
@@ -574,7 +574,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
         } else {
             // We cannot elide anything.
             self.set_sam_field(0b00);
-            self.set_field(idx, src);
+            self.set_field(idx, &src);
             idx += 16;
         }
 
@@ -593,7 +593,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
         self.set_dac_field(0);
         self.set_dam_field(0);
         self.set_m_field(0);
-        let dst = dst_addr.as_bytes();
+        let dst = dst_addr.octets();
         if dst_addr.is_multicast() {
             self.set_m_field(1);
 
@@ -619,7 +619,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
             } else {
                 self.set_dam_field(0b11);
 
-                self.set_field(idx, dst);
+                self.set_field(idx, &dst);
                 idx += 16;
             }
         } else if dst_addr.is_link_local() {
@@ -653,7 +653,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
         } else {
             self.set_dam_field(0b00);
 
-            self.set_field(idx, dst);
+            self.set_field(idx, &dst);
             idx += 16;
         }
 
@@ -771,7 +771,7 @@ impl Repr {
         len += if self.src_addr == ipv6::Address::UNSPECIFIED {
             0
         } else if self.src_addr.is_link_local() {
-            let src = self.src_addr.as_bytes();
+            let src = self.src_addr.octets();
             let ll = [src[14], src[15]];
 
             let is_eui_64 = self
@@ -799,7 +799,7 @@ impl Repr {
         };
 
         // Add the size of the destination header
-        let dst = self.dst_addr.as_bytes();
+        let dst = self.dst_addr.octets();
         len += if self.dst_addr.is_multicast() {
             if dst[1] == 0x02 && dst[2..15] == [0; 13] {
                 1

+ 1 - 0
src/wire/sixlowpan/mod.rs

@@ -6,6 +6,7 @@
 use super::{Error, Result};
 use crate::wire::ieee802154::Address as LlAddress;
 use crate::wire::ipv6;
+use crate::wire::ipv6::AddressExt;
 use crate::wire::IpProtocol;
 
 pub mod frag;

+ 2 - 2
src/wire/sixlowpan/nhc.rs

@@ -862,8 +862,8 @@ mod test {
 
         let payload = b"Hello World!";
 
-        let src_addr = ipv6::Address::default();
-        let dst_addr = ipv6::Address::default();
+        let src_addr = ipv6::Address::UNSPECIFIED;
+        let dst_addr = ipv6::Address::UNSPECIFIED;
 
         let len = udp.header_len() + payload.len();
         let mut buffer = [0u8; 127];