use byteorder::{ByteOrder, NetworkEndian}; use super::icmpv6::*; use time::Duration; use super::Ipv6Address; /// Getters for the Router Advertisement message header. /// See [RFC 4861 § 4.2]. /// /// [RFC 4861 § 4.2]: https://tools.ietf.org/html/rfc4861#section-4.2 impl> Packet { /// Return the current hop limit field. #[inline] pub fn current_hop_limit(&self) -> u8 { let data = self.buffer.as_ref(); data[field::CUR_HOP_LIMIT] } /// Return the Router Advertisement flags. #[inline] pub fn router_flags(&self) -> RouterFlags { let data = self.buffer.as_ref(); RouterFlags::from_bits_truncate(data[field::ROUTER_FLAGS]) } /// Return the router lifetime field. #[inline] pub fn router_lifetime(&self) -> Duration { let data = self.buffer.as_ref(); Duration::from_secs(NetworkEndian::read_u16(&data[field::ROUTER_LT]) as u64) } /// Return the reachable time field. #[inline] pub fn reachable_time(&self) -> Duration { let data = self.buffer.as_ref(); Duration::from_millis(NetworkEndian::read_u32(&data[field::REACHABLE_TM]) as u64) } /// Return the retransmit time field. #[inline] pub fn retrans_time(&self) -> Duration { let data = self.buffer.as_ref(); Duration::from_millis(NetworkEndian::read_u32(&data[field::RETRANS_TM]) as u64) } } /// Getters for the [Neighbor Solicitation], [Neighbor Advertisement], and /// [Redirect] message types. /// /// [Neighbor Solicitation]: https://tools.ietf.org/html/rfc4861#section-4.3 /// [Neighbor Advertisement]: https://tools.ietf.org/html/rfc4861#section-4.4 /// [Redirect]: https://tools.ietf.org/html/rfc4861#section-4.5 impl> Packet { /// Return the target address field. #[inline] pub fn target_addr(&self) -> Ipv6Address { let data = self.buffer.as_ref(); Ipv6Address::from_bytes(&data[field::TARGET_ADDR]) } } /// Getters for the Neighbor Solicitation message header. /// See [RFC 4861 § 4.3]. /// /// [RFC 4861 § 4.3]: https://tools.ietf.org/html/rfc4861#section-4.3 impl> Packet { /// Return the Neighbor Solicitation flags. #[inline] pub fn neighbor_flags(&self) -> NeighborFlags { let data = self.buffer.as_ref(); NeighborFlags::from_bits_truncate(data[field::NEIGH_FLAGS]) } } /// Getters for the Redirect message header. /// See [RFC 4861 § 4.5]. /// /// [RFC 4861 § 4.5]: https://tools.ietf.org/html/rfc4861#section-4.5 impl> Packet { /// Return the destination address field. #[inline] pub fn dest_addr(&self) -> Ipv6Address { let data = self.buffer.as_ref(); Ipv6Address::from_bytes(&data[field::DEST_ADDR]) } } /// Setters for the Router Solicitation message header. /// See [RFC 4861 § 4.1]. /// /// [RFC 4861 § 4.1]: https://tools.ietf.org/html/rfc4861#section-4.1 impl + AsMut<[u8]>> Packet { /// Clear the reserved field. #[inline] pub fn clear_reserved(&mut self) { let data = self.buffer.as_mut(); NetworkEndian::write_u32(&mut data[field::UNUSED], 0); } } /// Setters for the Router Advertisement message header. /// See [RFC 4861 § 4.2]. /// /// [RFC 4861 § 4.2]: https://tools.ietf.org/html/rfc4861#section-4.2 impl + AsMut<[u8]>> Packet { /// Set the current hop limit field. #[inline] pub fn set_current_hop_limit(&mut self, value: u8) { let data = self.buffer.as_mut(); data[field::CUR_HOP_LIMIT] = value; } /// Set the Router Advertisement flags. #[inline] pub fn set_router_flags(&mut self, flags: RouterFlags) { self.buffer.as_mut()[field::ROUTER_FLAGS] = flags.bits(); } /// Set the router lifetime field. #[inline] pub fn set_router_lifetime(&mut self, value: Duration) { let data = self.buffer.as_mut(); NetworkEndian::write_u16(&mut data[field::ROUTER_LT], value.secs() as u16); } /// Set the reachable time field. #[inline] pub fn set_reachable_time(&mut self, value: Duration) { let data = self.buffer.as_mut(); NetworkEndian::write_u32(&mut data[field::REACHABLE_TM], value.total_millis() as u32); } /// Set the retransmit time field. #[inline] pub fn set_retrans_time(&mut self, value: Duration) { let data = self.buffer.as_mut(); NetworkEndian::write_u32(&mut data[field::RETRANS_TM], value.total_millis() as u32); } } /// Setters for the [Neighbor Solicitation], [Neighbor Advertisement], and /// [Redirect] message types. /// /// [Neighbor Solicitation]: https://tools.ietf.org/html/rfc4861#section-4.3 /// [Neighbor Advertisement]: https://tools.ietf.org/html/rfc4861#section-4.4 /// [Redirect]: https://tools.ietf.org/html/rfc4861#section-4.5 impl + AsMut<[u8]>> Packet { /// Set the target address field. #[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()); } } /// Setters for the Neighbor Solicitation message header. /// See [RFC 4861 § 4.3]. /// /// [RFC 4861 § 4.3]: https://tools.ietf.org/html/rfc4861#section-4.3 impl + AsMut<[u8]>> Packet { /// Set the Neighbor Solicitation flags. #[inline] pub fn set_neighbor_flags(&mut self, flags: NeighborFlags) { self.buffer.as_mut()[field::NEIGH_FLAGS] = flags.bits(); } } /// Setters for the Redirect message header. /// See [RFC 4861 § 4.5]. /// /// [RFC 4861 § 4.5]: https://tools.ietf.org/html/rfc4861#section-4.5 impl + AsMut<[u8]>> Packet { /// Set the destination address field. #[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()); } } #[cfg(test)] mod test { use super::*; static ROUTER_ADVERT_BYTES: [u8; 16] = [0x86, 0x00, 0x2e, 0xf3, 0x40, 0x80, 0x03, 0x84, 0x00, 0x00, 0x03, 0x84, 0x00, 0x00, 0x03, 0x84]; #[test] fn test_router_advert_deconstruct() { let packet = Packet::new(&ROUTER_ADVERT_BYTES[..]); assert_eq!(packet.msg_type(), Message::RouterAdvert); assert_eq!(packet.msg_code(), 0); assert_eq!(packet.current_hop_limit(), 64); assert_eq!(packet.router_flags(), RouterFlags::MANAGED); assert_eq!(packet.router_lifetime(), Duration::from_secs(900)); assert_eq!(packet.reachable_time(), Duration::from_millis(900)); assert_eq!(packet.retrans_time(), Duration::from_millis(900)); } #[test] fn test_router_advert_construct() { let mut bytes = vec![0x0; 16]; let mut packet = Packet::new(&mut bytes); packet.set_msg_type(Message::RouterAdvert); packet.set_msg_code(0); packet.set_current_hop_limit(64); packet.set_router_flags(RouterFlags::MANAGED); packet.set_router_lifetime(Duration::from_secs(900)); packet.set_reachable_time(Duration::from_millis(900)); packet.set_retrans_time(Duration::from_millis(900)); packet.fill_checksum(); assert_eq!(&packet.into_inner()[..], &ROUTER_ADVERT_BYTES[..]); } }