ipv6fragment.rs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. use core::fmt;
  2. use {Error, Result};
  3. use byteorder::{ByteOrder, NetworkEndian};
  4. pub use super::IpProtocol as Protocol;
  5. /// A read/write wrapper around an IPv6 Fragment Header.
  6. #[derive(Debug, PartialEq)]
  7. pub struct Header<T: AsRef<[u8]>> {
  8. buffer: T
  9. }
  10. // Format of the Fragment Header
  11. //
  12. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  13. // | Next Header | Reserved | Fragment Offset |Res|M|
  14. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  15. // | Identification |
  16. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  17. //
  18. // See https://tools.ietf.org/html/rfc8200#section-4.5 for details.
  19. mod field {
  20. use wire::field::*;
  21. // 8-bit identifier of the header immediately following this header.
  22. pub const NXT_HDR: usize = 0;
  23. // 8-bit reserved field.
  24. pub const RESERVED: usize = 1;
  25. // 16-bit field containing the fragment offset, reserved and more fragments values.
  26. pub const FR_OF_M: Field = 2..4;
  27. // 32-bit field identifying the fragmented packet
  28. pub const IDENT: Field = 4..8;
  29. }
  30. impl<T: AsRef<[u8]>> Header<T> {
  31. /// Create a raw octet buffer with an IPv6 Fragment Header structure.
  32. pub fn new(buffer: T) -> Header<T> {
  33. Header { buffer }
  34. }
  35. /// Shorthand for a combination of [new] and [check_len].
  36. ///
  37. /// [new]: #method.new
  38. /// [check_len]: #method.check_len
  39. pub fn new_checked(buffer: T) -> Result<Header<T>> {
  40. let header = Self::new(buffer);
  41. header.check_len()?;
  42. Ok(header)
  43. }
  44. /// Ensure that no accessor method will panic if called.
  45. /// Returns `Err(Error::Truncated)` if the buffer is too short.
  46. pub fn check_len(&self) -> Result<()> {
  47. let data = self.buffer.as_ref();
  48. let len = data.len();
  49. if len < field::IDENT.end {
  50. Err(Error::Truncated)
  51. } else {
  52. Ok(())
  53. }
  54. }
  55. /// Consume the header, returning the underlying buffer.
  56. pub fn into_inner(self) -> T {
  57. self.buffer
  58. }
  59. /// Return the next header field.
  60. #[inline]
  61. pub fn next_header(&self) -> Protocol {
  62. let data = self.buffer.as_ref();
  63. Protocol::from(data[field::NXT_HDR])
  64. }
  65. /// Return the fragment offset field.
  66. #[inline]
  67. pub fn frag_offset(&self) -> u16 {
  68. let data = self.buffer.as_ref();
  69. NetworkEndian::read_u16(&data[field::FR_OF_M]) >> 3
  70. }
  71. /// Return more fragment flag field.
  72. #[inline]
  73. pub fn more_frags(&self) -> bool {
  74. let data = self.buffer.as_ref();
  75. (data[3] & 0x1) == 1
  76. }
  77. /// Return the fragment identification value field.
  78. #[inline]
  79. pub fn ident(&self) -> u32 {
  80. let data = self.buffer.as_ref();
  81. NetworkEndian::read_u32(&data[field::IDENT])
  82. }
  83. }
  84. impl<T: AsRef<[u8]> + AsMut<[u8]>> Header<T> {
  85. /// Set the next header field.
  86. #[inline]
  87. pub fn set_next_header(&mut self, value: Protocol) {
  88. let data = self.buffer.as_mut();
  89. data[field::NXT_HDR] = value.into();
  90. }
  91. /// Set reserved fields.
  92. ///
  93. /// Set 8-bit reserved field after the next header field.
  94. /// Set 2-bit reserved field between fragment offset and more fragments.
  95. #[inline]
  96. pub fn clear_reserved(&mut self) {
  97. let data = self.buffer.as_mut();
  98. data[field::RESERVED] = 0;
  99. // Retain the higher order 5 bits and lower order 1 bit
  100. data[3] = data[3] & 0xf9;
  101. }
  102. /// Set the fragment offset field.
  103. #[inline]
  104. pub fn set_frag_offset(&mut self, value: u16) {
  105. let data = self.buffer.as_mut();
  106. // Retain the lower order 3 bits
  107. let raw = ((value & 0x1fff) << 3) | ((data[3] & 0x7) as u16);
  108. NetworkEndian::write_u16(&mut data[field::FR_OF_M], raw);
  109. }
  110. /// Set the more fragments flag field.
  111. #[inline]
  112. pub fn set_more_frags(&mut self, value: bool) {
  113. let data = self.buffer.as_mut();
  114. // Retain the high order 7 bits
  115. let raw = (data[3] & 0xfe) | (value as u8 & 0x1);
  116. data[3] = raw;
  117. }
  118. /// Set the fragmentation identification field.
  119. #[inline]
  120. pub fn set_ident(&mut self, value: u32) {
  121. let data = self.buffer.as_mut();
  122. NetworkEndian::write_u32(&mut data[field::IDENT], value);
  123. }
  124. }
  125. impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Header<&'a T> {
  126. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  127. match Repr::parse(self) {
  128. Ok(repr) => write!(f, "{}", repr),
  129. Err(err) => {
  130. write!(f, "IPv6 Fragment ({})", err)?;
  131. Ok(())
  132. }
  133. }
  134. }
  135. }
  136. /// A high-level representation of an IPv6 Fragment header.
  137. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  138. pub struct Repr {
  139. /// The type of header immediately following the Fragment header.
  140. pub next_header: Protocol,
  141. /// The offset of the data following this header, relative to the start of the Fragmentable
  142. /// Part of the original packet.
  143. pub frag_offset: u16,
  144. /// Whethere are not there are more fragments following this header
  145. pub more_frags: bool,
  146. /// The identification for every packet that is fragmented.
  147. pub ident: u32,
  148. }
  149. impl Repr {
  150. /// Parse an IPv6 Fragment Header and return a high-level representation.
  151. pub fn parse<T>(header: &Header<&T>) -> Result<Repr> where T: AsRef<[u8]> + ?Sized {
  152. Ok(Repr {
  153. next_header: header.next_header(),
  154. frag_offset: header.frag_offset(),
  155. more_frags: header.more_frags(),
  156. ident: header.ident()
  157. })
  158. }
  159. /// Return the length, in bytes, of a header that will be emitted from this high-level
  160. /// representation.
  161. pub fn buffer_len(&self) -> usize {
  162. field::IDENT.end
  163. }
  164. /// Emit a high-level representation into an IPv6 Fragment Header.
  165. pub fn emit<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized>(&self, header: &mut Header<&mut T>) {
  166. header.set_next_header(self.next_header);
  167. header.clear_reserved();
  168. header.set_frag_offset(self.frag_offset);
  169. header.set_more_frags(self.more_frags);
  170. header.set_ident(self.ident);
  171. }
  172. }
  173. impl<'a> fmt::Display for Repr {
  174. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  175. write!(f, "IPv6 Fragment next_hdr={} offset={} more={} ident={}",
  176. self.next_header, self.frag_offset, self.more_frags, self.ident)
  177. }
  178. }
  179. #[cfg(test)]
  180. mod test {
  181. use super::*;
  182. // A Fragment Header with more fragments remaining
  183. static BYTES_HEADER_MORE_FRAG: [u8; 8] = [0x6, 0x0, 0x0, 0x1,
  184. 0x0, 0x0, 0x30, 0x39];
  185. // A Fragment Header with no more fragments remaining
  186. static BYTES_HEADER_LAST_FRAG: [u8; 8] = [0x6, 0x0, 0xa, 0x0,
  187. 0x0, 0x1, 0x9, 0x32];
  188. #[test]
  189. fn test_check_len() {
  190. // less than 8 bytes
  191. assert_eq!(Err(Error::Truncated), Header::new(&BYTES_HEADER_MORE_FRAG[..7]).check_len());
  192. // valid
  193. assert_eq!(Ok(()), Header::new(&BYTES_HEADER_MORE_FRAG).check_len());
  194. }
  195. #[test]
  196. fn test_header_deconstruct() {
  197. let header = Header::new(&BYTES_HEADER_MORE_FRAG);
  198. assert_eq!(header.next_header(), Protocol::Tcp);
  199. assert_eq!(header.frag_offset(), 0);
  200. assert_eq!(header.more_frags(), true);
  201. assert_eq!(header.ident(), 12345);
  202. let header = Header::new(&BYTES_HEADER_LAST_FRAG);
  203. assert_eq!(header.next_header(), Protocol::Tcp);
  204. assert_eq!(header.frag_offset(), 320);
  205. assert_eq!(header.more_frags(), false);
  206. assert_eq!(header.ident(), 67890);
  207. }
  208. #[test]
  209. fn test_repr_parse_valid() {
  210. let header = Header::new(&BYTES_HEADER_MORE_FRAG);
  211. let repr = Repr::parse(&header).unwrap();
  212. assert_eq!(repr,
  213. Repr{ next_header: Protocol::Tcp, frag_offset: 0, more_frags: true, ident: 12345 });
  214. let header = Header::new(&BYTES_HEADER_LAST_FRAG);
  215. let repr = Repr::parse(&header).unwrap();
  216. assert_eq!(repr,
  217. Repr{ next_header: Protocol::Tcp, frag_offset: 320, more_frags: false, ident: 67890 });
  218. }
  219. #[test]
  220. fn test_repr_emit() {
  221. let repr = Repr{ next_header: Protocol::Tcp, frag_offset: 0, more_frags: true, ident: 12345 };
  222. let mut bytes = [0u8; 8];
  223. let mut header = Header::new(&mut bytes);
  224. repr.emit(&mut header);
  225. assert_eq!(header.into_inner(), &BYTES_HEADER_MORE_FRAG[0..8]);
  226. let repr = Repr{ next_header: Protocol::Tcp, frag_offset: 320, more_frags: false, ident: 67890 };
  227. let mut bytes = [0u8; 8];
  228. let mut header = Header::new(&mut bytes);
  229. repr.emit(&mut header);
  230. assert_eq!(header.into_inner(), &BYTES_HEADER_LAST_FRAG[0..8]);
  231. }
  232. #[test]
  233. fn test_buffer_len() {
  234. let header = Header::new(&BYTES_HEADER_MORE_FRAG);
  235. let repr = Repr::parse(&header).unwrap();
  236. assert_eq!(repr.buffer_len(), BYTES_HEADER_MORE_FRAG.len());
  237. }
  238. }