浏览代码

Implement TCP representation parsing and emission.

whitequark 8 年之前
父节点
当前提交
5a85a5c4f9
共有 5 个文件被更改,包括 145 次插入8 次删除
  1. 3 2
      src/wire/icmpv4.rs
  2. 8 3
      src/wire/ipv4.rs
  3. 2 0
      src/wire/mod.rs
  4. 129 1
      src/wire/tcp.rs
  5. 3 2
      src/wire/udp.rs

+ 3 - 2
src/wire/icmpv4.rs

@@ -462,9 +462,10 @@ mod test {
 
     #[test]
     fn test_echo_emit() {
-        let mut bytes = vec![0; 12];
+        let repr = echo_packet_repr();
+        let mut bytes = vec![0; repr.buffer_len()];
         let mut packet = Packet::new(&mut bytes).unwrap();
-        echo_packet_repr().emit(&mut packet);
+        repr.emit(&mut packet);
         assert_eq!(&packet.into_inner()[..], &ECHO_PACKET_BYTES[..]);
     }
 }

+ 8 - 3
src/wire/ipv4.rs

@@ -555,7 +555,10 @@ mod test {
          0x40, 0x01, 0xd2, 0x79,
          0x11, 0x12, 0x13, 0x14,
          0x21, 0x22, 0x23, 0x24,
-         0x00, 0x00, 0x00, 0x00];
+         0xaa, 0x00, 0x00, 0xff];
+
+    static REPR_PAYLOAD_BYTES: [u8; 4] =
+        [0xaa, 0x00, 0x00, 0xff];
 
     fn packet_repr() -> Repr {
         Repr {
@@ -574,9 +577,11 @@ mod test {
 
     #[test]
     fn test_emit() {
-        let mut bytes = vec![0; 24];
+        let repr = packet_repr();
+        let mut bytes = vec![0; repr.buffer_len() + REPR_PAYLOAD_BYTES.len()];
         let mut packet = Packet::new(&mut bytes).unwrap();
-        packet_repr().emit(&mut packet, 4);
+        repr.emit(&mut packet, REPR_PAYLOAD_BYTES.len());
+        packet.payload_mut().copy_from_slice(&REPR_PAYLOAD_BYTES);
         assert_eq!(&packet.into_inner()[..], &REPR_PACKET_BYTES[..]);
     }
 }

+ 2 - 0
src/wire/mod.rs

@@ -119,3 +119,5 @@ pub use self::udp::Packet as UdpPacket;
 pub use self::udp::Repr as UdpRepr;
 
 pub use self::tcp::Packet as TcpPacket;
+pub use self::tcp::Repr as TcpRepr;
+pub use self::tcp::Control as TcpControl;

+ 129 - 1
src/wire/tcp.rs

@@ -239,7 +239,9 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     #[inline(always)]
     pub fn clear_flags(&mut self) {
         let data = self.buffer.as_mut();
-        NetworkEndian::write_u16(&mut data[field::FLAGS], 0)
+        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
+        let raw = raw & !0x0fff;
+        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
     }
 
     /// Set the FIN flag.
@@ -382,6 +384,96 @@ impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> Packet<&'a mut T> {
     }
 }
 
+/// A high-level representation of a Transmission Control Protocol packet.
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub struct Repr<'a> {
+    src_port:   u16,
+    dst_port:   u16,
+    seq_number: u32,
+    ack_number: Option<u32>,
+    window_len: u16,
+    control:    Control,
+    payload:    &'a [u8]
+}
+
+/// The control flags of a Transmission Control Protocol packet.
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub enum Control {
+    None,
+    Syn,
+    Fin,
+    Rst
+}
+
+impl<'a> Repr<'a> {
+    /// Parse a Transmission Control Protocol packet and return a high-level representation.
+    pub fn parse<T: ?Sized>(packet: &Packet<&'a T>,
+                            src_addr: &InternetAddress,
+                            dst_addr: &InternetAddress) -> Result<Repr<'a>, Error>
+            where T: AsRef<[u8]> {
+        // Source and destination ports must be present.
+        if packet.src_port() == 0 { return Err(Error::Malformed) }
+        if packet.dst_port() == 0 { return Err(Error::Malformed) }
+        // Valid checksum is expected...
+        if !packet.verify_checksum(src_addr, dst_addr) { return Err(Error::Checksum) }
+
+        let control =
+            match (packet.syn(), packet.fin(), packet.rst()) {
+                (false, false, false) => Control::None,
+                (true,  false, false) => Control::Syn,
+                (false, true,  false) => Control::Fin,
+                (false, false, true ) => Control::Rst,
+                _ => return Err(Error::Malformed)
+            };
+        let ack_number =
+            match packet.ack() {
+                true  => Some(packet.ack_number()),
+                false => None
+            };
+        // The PSH flag is ignored.
+        // The URG flag and the urgent field is ignored. This behavior is standards-compliant,
+        // however, most deployed systems (e.g. Linux) are *not* standards-compliant, and would
+        // cut the byte at the urgent pointer from the stream.
+
+        Ok(Repr {
+            src_port:   packet.src_port(),
+            dst_port:   packet.dst_port(),
+            seq_number: packet.seq_number(),
+            ack_number: ack_number,
+            window_len: packet.window_len(),
+            control:    control,
+            payload:    packet.payload()
+        })
+    }
+
+    /// Return the length of a packet that will be emitted from this high-level representation.
+    pub fn buffer_len(&self) -> usize {
+        field::URGENT.end + self.payload.len()
+    }
+
+    /// Emit a high-level representation into a Transmission Control Protocol packet.
+    pub fn emit<T: ?Sized>(&self, packet: &mut Packet<&mut T>,
+                           src_addr: &InternetAddress,
+                           dst_addr: &InternetAddress)
+            where T: AsRef<[u8]> + AsMut<[u8]> {
+        packet.set_src_port(self.src_port);
+        packet.set_dst_port(self.dst_port);
+        packet.set_seq_number(self.seq_number);
+        packet.set_ack_number(self.ack_number.unwrap_or(0));
+        packet.set_window_len(self.window_len);
+        packet.set_header_len(20);
+        packet.clear_flags();
+        match self.control {
+            Control::None => (),
+            Control::Syn  => packet.set_syn(true),
+            Control::Fin  => packet.set_fin(true),
+            Control::Rst  => packet.set_rst(true)
+        }
+        packet.payload_mut().copy_from_slice(self.payload);
+        packet.fill_checksum(src_addr, dst_addr)
+    }
+}
+
 #[cfg(test)]
 mod test {
     use wire::Ipv4Address;
@@ -444,4 +536,40 @@ mod test {
         packet.fill_checksum(&SRC_ADDR.into(), &DST_ADDR.into());
         assert_eq!(&packet.into_inner()[..], &PACKET_BYTES[..]);
     }
+
+    static SYN_PACKET_BYTES: [u8; 24] =
+        [0xbf, 0x00, 0x00, 0x50,
+         0x01, 0x23, 0x45, 0x67,
+         0x00, 0x00, 0x00, 0x00,
+         0x50, 0x02, 0x01, 0x23,
+         0x7a, 0x8d, 0x00, 0x00,
+         0xaa, 0x00, 0x00, 0xff];
+
+    fn packet_repr() -> Repr<'static> {
+        Repr {
+            src_port:   48896,
+            dst_port:   80,
+            seq_number: 0x01234567,
+            ack_number: None,
+            window_len: 0x0123,
+            control:    Control::Syn,
+            payload:    &PAYLOAD_BYTES
+        }
+    }
+
+    #[test]
+    fn test_parse() {
+        let packet = Packet::new(&SYN_PACKET_BYTES[..]).unwrap();
+        let repr = Repr::parse(&packet, &SRC_ADDR.into(), &DST_ADDR.into()).unwrap();
+        assert_eq!(repr, packet_repr());
+    }
+
+    #[test]
+    fn test_emit() {
+        let repr = packet_repr();
+        let mut bytes = vec![0; repr.buffer_len()];
+        let mut packet = Packet::new(&mut bytes).unwrap();
+        repr.emit(&mut packet, &SRC_ADDR.into(), &DST_ADDR.into());
+        assert_eq!(&packet.into_inner()[..], &SYN_PACKET_BYTES[..]);
+    }
 }

+ 3 - 2
src/wire/udp.rs

@@ -298,9 +298,10 @@ mod test {
 
     #[test]
     fn test_emit() {
-        let mut bytes = vec![0; 12];
+        let repr = packet_repr();
+        let mut bytes = vec![0; repr.buffer_len()];
         let mut packet = Packet::new(&mut bytes).unwrap();
-        packet_repr().emit(&mut packet, &SRC_ADDR.into(), &DST_ADDR.into());
+        repr.emit(&mut packet, &SRC_ADDR.into(), &DST_ADDR.into());
         assert_eq!(&packet.into_inner()[..], &PACKET_BYTES[..]);
     }
 }