pcap_writer.rs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. use core::cell::RefCell;
  2. #[cfg(feature = "std")]
  3. use std::io::Write;
  4. use byteorder::{ByteOrder, NativeEndian};
  5. use {Error, Result};
  6. use super::{DeviceLimits, Device};
  7. enum_with_unknown! {
  8. /// Captured packet header type.
  9. pub doc enum PcapLinkType(u32) {
  10. /// Ethernet frames
  11. Ethernet = 1,
  12. /// IPv4 or IPv6 packets (depending on the version field)
  13. Ip = 101
  14. }
  15. }
  16. /// Packet capture mode.
  17. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  18. pub enum PcapMode {
  19. /// Capture both received and transmitted packets.
  20. Both,
  21. /// Capture only received packets.
  22. RxOnly,
  23. /// Capture only transmitted packets.
  24. TxOnly
  25. }
  26. /// A packet capture sink.
  27. ///
  28. /// A sink is an interface to the platform functions, providing timestamping
  29. /// and streaming data output.
  30. pub trait PcapSink {
  31. /// Write data into the sink.
  32. fn write(&self, data: &[u8]);
  33. /// Write an `u16` into the sink, in native byte order.
  34. fn write_u16(&self, value: u16) {
  35. let mut bytes = [0u8; 2];
  36. NativeEndian::write_u16(&mut bytes, value);
  37. self.write(&bytes[..])
  38. }
  39. /// Write an `u32` into the sink, in native byte order.
  40. fn write_u32(&self, value: u32) {
  41. let mut bytes = [0u8; 4];
  42. NativeEndian::write_u32(&mut bytes, value);
  43. self.write(&bytes[..])
  44. }
  45. /// Write the libpcap global header into the sink.
  46. ///
  47. /// This method may be overridden e.g. if special synchronization is necessary.
  48. fn global_header(&self, link_type: PcapLinkType) {
  49. self.write_u32(0xa1b2c3d4); // magic number
  50. self.write_u16(2); // major version
  51. self.write_u16(4); // minor version
  52. self.write_u32(0); // timezone (= UTC)
  53. self.write_u32(0); // accuracy (not used)
  54. self.write_u32(65535); // maximum packet length
  55. self.write_u32(link_type.into()); // link-layer header type
  56. }
  57. /// Write the libpcap packet header into the sink.
  58. ///
  59. /// See also the note for [global_header](#method.global_header).
  60. fn packet_header(&self, timestamp: u64, length: usize) {
  61. assert!(length <= 65535);
  62. let (seconds, micros) = (timestamp / 1000, timestamp % 1000 * 1000);
  63. self.write_u32(seconds as u32); // timestamp seconds
  64. self.write_u32(micros as u32); // timestamp microseconds
  65. self.write_u32(length as u32); // captured length
  66. self.write_u32(length as u32); // original length
  67. }
  68. /// Write the libpcap packet header followed by packet data into the sink.
  69. ///
  70. /// See also the note for [global_header](#method.global_header).
  71. fn packet(&self, timestamp: u64, packet: &[u8]) {
  72. self.packet_header(timestamp, packet.len());
  73. self.write(packet)
  74. }
  75. }
  76. impl<T: AsRef<PcapSink>> PcapSink for T {
  77. fn write(&self, data: &[u8]) {
  78. self.as_ref().write(data)
  79. }
  80. }
  81. #[cfg(feature = "std")]
  82. impl<T: AsMut<Write>> PcapSink for RefCell<T> {
  83. fn write(&self, data: &[u8]) {
  84. self.borrow_mut().as_mut().write_all(data).expect("cannot write")
  85. }
  86. fn packet(&self, timestamp: u64, packet: &[u8]) {
  87. self.packet_header(timestamp, packet.len());
  88. PcapSink::write(self, packet);
  89. self.borrow_mut().as_mut().flush().expect("cannot flush")
  90. }
  91. }
  92. /// A packet capture writer device.
  93. ///
  94. /// Every packet transmitted or received through this device is timestamped
  95. /// and written (in the [libpcap] format) using the provided [sink].
  96. /// Note that writes are fine-grained, and buffering is recommended.
  97. ///
  98. /// The packet sink should be cheaply cloneable, as it is cloned on every
  99. /// transmitted packet. For example, `&'a mut Vec<u8>` is cheaply cloneable
  100. /// but `&std::io::File`
  101. ///
  102. /// [libpcap]: https://wiki.wireshark.org/Development/LibpcapFileFormat
  103. /// [sink]: trait.PcapSink.html
  104. #[derive(Debug)]
  105. pub struct PcapWriter<D: Device, S: PcapSink + Clone> {
  106. lower: D,
  107. sink: S,
  108. mode: PcapMode
  109. }
  110. impl<D: Device, S: PcapSink + Clone> PcapWriter<D, S> {
  111. /// Creates a packet capture writer.
  112. pub fn new(lower: D, sink: S, mode: PcapMode, link_type: PcapLinkType) -> PcapWriter<D, S> {
  113. sink.global_header(link_type);
  114. PcapWriter { lower, sink, mode }
  115. }
  116. }
  117. impl<D: Device, S: PcapSink + Clone> Device for PcapWriter<D, S> {
  118. type RxBuffer = D::RxBuffer;
  119. type TxBuffer = TxBuffer<D::TxBuffer, S>;
  120. fn limits(&self) -> DeviceLimits { self.lower.limits() }
  121. fn receive(&mut self, timestamp: u64) -> Result<Self::RxBuffer> {
  122. let buffer = self.lower.receive(timestamp)?;
  123. match self.mode {
  124. PcapMode::Both | PcapMode::RxOnly =>
  125. self.sink.packet(timestamp, buffer.as_ref()),
  126. PcapMode::TxOnly => ()
  127. }
  128. Ok(buffer)
  129. }
  130. fn transmit(&mut self, timestamp: u64, length: usize) -> Result<Self::TxBuffer> {
  131. let buffer = self.lower.transmit(timestamp, length)?;
  132. Ok(TxBuffer { buffer, timestamp, sink: self.sink.clone(), mode: self.mode })
  133. }
  134. }
  135. #[doc(hidden)]
  136. pub struct TxBuffer<B: AsRef<[u8]> + AsMut<[u8]>, S: PcapSink> {
  137. buffer: B,
  138. timestamp: u64,
  139. sink: S,
  140. mode: PcapMode
  141. }
  142. impl<B, S> AsRef<[u8]> for TxBuffer<B, S>
  143. where B: AsRef<[u8]> + AsMut<[u8]>, S: PcapSink {
  144. fn as_ref(&self) -> &[u8] { self.buffer.as_ref() }
  145. }
  146. impl<B, S> AsMut<[u8]> for TxBuffer<B, S>
  147. where B: AsRef<[u8]> + AsMut<[u8]>, S: PcapSink {
  148. fn as_mut(&mut self) -> &mut [u8] { self.buffer.as_mut() }
  149. }
  150. impl<B, S> Drop for TxBuffer<B, S>
  151. where B: AsRef<[u8]> + AsMut<[u8]>, S: PcapSink {
  152. fn drop(&mut self) {
  153. match self.mode {
  154. PcapMode::Both | PcapMode::TxOnly =>
  155. self.sink.packet(self.timestamp, self.as_ref()),
  156. PcapMode::RxOnly => ()
  157. }
  158. }
  159. }