Ver Fonte

Respond with ICMP echo request data in echo reply.

whitequark há 8 anos atrás
pai
commit
be4ea0a55e
5 ficheiros alterados com 33 adições e 26 exclusões
  1. 1 1
      README.md
  2. 4 3
      src/iface/ethernet.rs
  3. 3 1
      src/wire/ethernet.rs
  4. 13 11
      src/wire/icmpv4.rs
  5. 12 10
      src/wire/ipv4.rs

+ 1 - 1
README.md

@@ -66,7 +66,7 @@ a specific user:
 ```sh
 sudo ip tuntap add name tap0 mode tap user $USER
 sudo ip link set tap0 up
-sudo ip addr add 192.168.69.100 dev tap0
+sudo ip addr add 192.168.69.100/24 dev tap0
 ```
 
 ### smoltcpdump

+ 4 - 3
src/iface/ethernet.rs

@@ -79,10 +79,11 @@ impl<'a, DeviceT: Device, ArpCacheT: ArpCache> Interface<'a, DeviceT, ArpCacheT>
             Arp(ArpRepr),
             Icmpv4(Ipv4Repr, Icmpv4Repr<'a>)
         }
-        let mut response = Response::Nop;
 
         let rx_buffer = try!(self.device.receive());
-        let eth_frame = try!(EthernetFrame::new(rx_buffer));
+        let eth_frame = try!(EthernetFrame::new(&rx_buffer));
+
+        let mut response = Response::Nop;
         match eth_frame.ethertype() {
             // Snoop all ARP traffic, and respond to ARP packets directed at us.
             EthernetProtocolType::Arp => {
@@ -144,7 +145,7 @@ impl<'a, DeviceT: Device, ArpCacheT: ArpCache> Interface<'a, DeviceT, ArpCacheT>
                                 let icmp_reply_repr = Icmpv4Repr::EchoReply {
                                     ident:  ident,
                                     seq_no: seq_no,
-                                    data:   &[]
+                                    data:   data
                                 };
                                 response = Response::Icmpv4(ip_reply_repr, icmp_reply_repr)
                             }

+ 3 - 1
src/wire/ethernet.rs

@@ -116,10 +116,12 @@ impl<T: AsRef<[u8]>> Frame<T> {
         let raw = NetworkEndian::read_u16(&data[field::ETHERTYPE]);
         EtherType::from(raw)
     }
+}
 
+impl<'a, T: AsRef<[u8]> + ?Sized> Frame<&'a T> {
     /// Return a pointer to the payload, without checking for 802.1Q.
     #[inline(always)]
-    pub fn payload(&self) -> &[u8] {
+    pub fn payload(&self) -> &'a [u8] {
         let data = self.buffer.as_ref();
         &data[field::PAYLOAD]
     }

+ 13 - 11
src/wire/icmpv4.rs

@@ -214,23 +214,25 @@ impl<T: AsRef<[u8]>> Packet<T> {
         }
     }
 
-    /// Return a pointer to the type-specific data.
-    #[inline(always)]
-    pub fn data(&self) -> &[u8] {
-        let data = self.buffer.as_ref();
-        &data[self.header_len()..]
-    }
-
     /// Validate the header checksum.
     pub fn verify_checksum(&self) -> bool {
         let checksum = {
             let data = self.buffer.as_ref();
-            rfc1071_checksum(field::CHECKSUM.start, &data[..self.header_len()])
+            rfc1071_checksum(field::CHECKSUM.start, data)
         };
         self.checksum() == checksum
     }
 }
 
+impl<'a, T: AsRef<[u8]> + ?Sized> Packet<&'a T> {
+    /// Return a pointer to the type-specific data.
+    #[inline(always)]
+    pub fn data(&self) -> &'a [u8] {
+        let data = self.buffer.as_ref();
+        &data[self.header_len()..]
+    }
+}
+
 impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     /// Set the message type field.
     #[inline(always)]
@@ -285,7 +287,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     pub fn fill_checksum(&mut self) {
         let checksum = {
             let data = self.buffer.as_ref();
-            rfc1071_checksum(field::CHECKSUM.start, &data[..self.header_len()])
+            rfc1071_checksum(field::CHECKSUM.start, data)
         };
         self.set_checksum(checksum)
     }
@@ -312,7 +314,7 @@ impl<'a> Repr<'a> {
     /// Parse an Internet Control Message Protocol version 4 packet and return
     /// a high-level representation, or return `Err(())` if the packet is not recognized
     /// or is malformed.
-    pub fn parse<T: AsRef<[u8]>>(packet: &'a Packet<T>) -> Result<Repr<'a>, Error> {
+    pub fn parse<T: AsRef<[u8]> + ?Sized>(packet: &Packet<&'a T>) -> Result<Repr<'a>, Error> {
         match (packet.msg_type(), packet.msg_code()) {
             (Type::EchoRequest, 0) => {
                 Ok(Repr::EchoRequest {
@@ -367,7 +369,7 @@ impl<'a> Repr<'a> {
     }
 }
 
-impl<T: AsRef<[u8]>> fmt::Display for Packet<T> {
+impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match Repr::parse(self) {
             Ok(repr) => write!(f, "{}", repr),

+ 12 - 10
src/wire/ipv4.rs

@@ -209,14 +209,6 @@ impl<T: AsRef<[u8]>> Packet<T> {
         Address::from_bytes(&data[field::DST_ADDR])
     }
 
-    /// Return a pointer to the payload.
-    #[inline(always)]
-    pub fn payload(&self) -> &[u8] {
-        let range = self.header_len() as usize;
-        let data = self.buffer.as_ref();
-        &data[range..]
-    }
-
     /// Validate the header checksum.
     pub fn verify_checksum(&self) -> bool {
         let checksum = {
@@ -227,6 +219,16 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 }
 
+impl<'a, T: AsRef<[u8]> + ?Sized> Packet<&'a T> {
+    /// Return a pointer to the payload.
+    #[inline(always)]
+    pub fn payload(&self) -> &'a [u8] {
+        let range = self.header_len() as usize;
+        let data = self.buffer.as_ref();
+        &data[range..]
+    }
+}
+
 impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     /// Set the version field.
     #[inline(always)]
@@ -359,7 +361,7 @@ pub struct Repr {
 impl Repr {
     /// Parse an Internet Protocol version 4 packet and return a high-level representation,
     /// or return `Err(())` if the packet is not recognized or is malformed.
-    pub fn parse<T: AsRef<[u8]>>(packet: &Packet<T>) -> Result<Repr, Error> {
+    pub fn parse<T: AsRef<[u8]> + ?Sized>(packet: &Packet<&T>) -> Result<Repr, Error> {
         // Version 4 is expected.
         if packet.version() != 4 { return Err(Error::Malformed) }
         // Valid checksum is expected.
@@ -403,7 +405,7 @@ impl Repr {
     }
 }
 
-impl<T: AsRef<[u8]>> fmt::Display for Packet<T> {
+impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match Repr::parse(self) {
             Ok(repr) => write!(f, "{}", repr),