Prechádzať zdrojové kódy

Sort out buffer lengths.

whitequark 8 rokov pred
rodič
commit
85ae54a488

+ 0 - 1
README.md

@@ -21,7 +21,6 @@ The only supported medium is Ethernet.
   * ARP packets (including gratuitous requests and replies) are supported.
   * 802.3 and 802.1Q are **not** supported.
   * Jumbo frames are **not** supported.
-  * Frame check sequence calculation is **not** supported.
 
 ### IP layer
 

+ 24 - 18
src/iface/ethernet.rs

@@ -216,10 +216,10 @@ impl<'a, 'b: 'a,
             _ => return Err(Error::Unrecognized)
         }
 
-        let tx_size = self.device.mtu();
         match response {
             Response::Arp(repr) => {
-                let mut tx_buffer = try!(self.device.transmit(tx_size));
+                let tx_len = EthernetFrame::<&[u8]>::buffer_len(repr.buffer_len());
+                let mut tx_buffer = try!(self.device.transmit(tx_len));
                 let mut frame = try!(EthernetFrame::new(&mut tx_buffer));
                 frame.set_src_addr(self.hardware_addr);
                 frame.set_dst_addr(match repr {
@@ -239,14 +239,16 @@ impl<'a, 'b: 'a,
                         Some(hardware_addr) => hardware_addr
                     };
 
-                let mut tx_buffer = try!(self.device.transmit(tx_size));
+                let tx_len = EthernetFrame::<&[u8]>::buffer_len(ip_repr.buffer_len() +
+                                                                icmp_repr.buffer_len());
+                let mut tx_buffer = try!(self.device.transmit(tx_len));
                 let mut frame = try!(EthernetFrame::new(&mut tx_buffer));
                 frame.set_src_addr(self.hardware_addr);
                 frame.set_dst_addr(dst_hardware_addr);
                 frame.set_ethertype(EthernetProtocolType::Ipv4);
 
                 let mut ip_packet = try!(Ipv4Packet::new(frame.payload_mut()));
-                ip_repr.emit(&mut ip_packet, icmp_repr.len());
+                ip_repr.emit(&mut ip_packet, icmp_repr.buffer_len());
 
                 let mut icmp_packet = try!(Icmpv4Packet::new(ip_packet.payload_mut()));
                 icmp_repr.emit(&mut icmp_packet);
@@ -261,19 +263,6 @@ impl<'a, 'b: 'a,
 
                 for socket in self.sockets.borrow_mut() {
                     let result = socket.dispatch(&mut |src_addr, dst_addr, protocol, payload| {
-                        let dst_hardware_addr =
-                            match arp_cache.lookup(*dst_addr) {
-                                None => return Err(Error::Unaddressable),
-                                Some(hardware_addr) => hardware_addr
-                            };
-
-                        let mut tx_buffer = try!(device.transmit(tx_size));
-                        let mut frame = try!(EthernetFrame::new(&mut tx_buffer));
-                        frame.set_src_addr(src_hardware_addr);
-                        frame.set_dst_addr(dst_hardware_addr);
-                        frame.set_ethertype(EthernetProtocolType::Ipv4);
-
-                        let mut ip_packet = try!(Ipv4Packet::new(frame.payload_mut()));
                         let ip_repr =
                             match (src_addr, dst_addr) {
                                 (&InternetAddress::Ipv4(src_addr),
@@ -286,7 +275,24 @@ impl<'a, 'b: 'a,
                                 },
                                 _ => unreachable!()
                             };
-                        ip_repr.emit(&mut ip_packet, payload.len());
+
+                        let dst_hardware_addr =
+                            match arp_cache.lookup(*dst_addr) {
+                                None => return Err(Error::Unaddressable),
+                                Some(hardware_addr) => hardware_addr
+                            };
+
+                        let tx_len = EthernetFrame::<&[u8]>::buffer_len(ip_repr.buffer_len() +
+                                                                        payload.buffer_len());
+                        let mut tx_buffer = try!(device.transmit(tx_len));
+                        let mut frame = try!(EthernetFrame::new(&mut tx_buffer));
+                        frame.set_src_addr(src_hardware_addr);
+                        frame.set_dst_addr(dst_hardware_addr);
+                        frame.set_ethertype(EthernetProtocolType::Ipv4);
+
+                        let mut ip_packet = try!(Ipv4Packet::new(frame.payload_mut()));
+                        ip_repr.emit(&mut ip_packet, payload.buffer_len());
+
                         payload.emit(src_addr, dst_addr, ip_packet.payload_mut());
 
                         Ok(())

+ 2 - 1
src/phy/raw_socket.rs

@@ -38,7 +38,8 @@ impl Device for RawSocket {
     fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
         let mut lower = self.lower.borrow_mut();
         let mut buffer = vec![0; self.mtu];
-        lower.recv(&mut buffer[..]).unwrap();
+        let size = lower.recv(&mut buffer[..]).unwrap();
+        buffer.resize(size, 0);
         Ok(buffer)
     }
 

+ 2 - 1
src/phy/tap_interface.rs

@@ -38,7 +38,8 @@ impl Device for TapInterface {
     fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
         let mut lower = self.lower.borrow_mut();
         let mut buffer = vec![0; self.mtu];
-        lower.recv(&mut buffer[..]).unwrap();
+        let size = lower.recv(&mut buffer[..]).unwrap();
+        buffer.resize(size, 0);
         Ok(buffer)
     }
 

+ 2 - 2
src/socket/mod.rs

@@ -27,8 +27,8 @@ pub use self::tcp::Buffer as TcpBuffer;
 /// This interface abstracts the various types of packets layered under the IP protocol,
 /// and serves as an accessory to [trait Socket](trait.Socket.html).
 pub trait PacketRepr {
-    /// Return the length required to serialize this high-level representation.
-    fn len(&self) -> usize;
+    /// Return the length of the buffer required to serialize this high-level representation.
+    fn buffer_len(&self) -> usize;
 
     /// Emit this high-level representation into a sequence of octets.
     fn emit(&self, src_addr: &Address, dst_addr: &Address, payload: &mut [u8]);

+ 2 - 2
src/socket/udp.rs

@@ -201,8 +201,8 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
 }
 
 impl<'a> PacketRepr for UdpRepr<'a> {
-    fn len(&self) -> usize {
-        self.len()
+    fn buffer_len(&self) -> usize {
+        self.buffer_len()
     }
 
     fn emit(&self, src_addr: &Address, dst_addr: &Address, payload: &mut [u8]) {

+ 8 - 0
src/wire/arp.rs

@@ -263,6 +263,14 @@ impl Repr {
         }
     }
 
+    /// Return the length of a packet that will be emitted from this high-level representation.
+    pub fn buffer_len(&self) -> usize {
+        match self {
+            &Repr::EthernetIpv4 { .. } => field::TPA(6, 4).end,
+            &Repr::__Nonexhaustive => unreachable!()
+        }
+    }
+
     /// Emit a high-level representation into an Address Resolution Protocol packet.
     pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, packet: &mut Packet<T>) {
         match self {

+ 10 - 0
src/wire/ethernet.rs

@@ -1,5 +1,7 @@
+use core::cmp;
 use core::fmt;
 use byteorder::{ByteOrder, NetworkEndian};
+
 use Error;
 
 enum_with_unknown! {
@@ -95,6 +97,14 @@ impl<T: AsRef<[u8]>> Frame<T> {
         self.buffer
     }
 
+    /// Return the length of a buffer required to hold a packet with the payload
+    /// of a given length.
+    pub fn buffer_len(payload_len: usize) -> usize {
+        // Minimal frame size is 64, but that includes FCS, which the network device
+        // is taking care of for us.
+        cmp::max(field::PAYLOAD.start + payload_len, 60)
+    }
+
     /// Return the destination address field.
     #[inline(always)]
     pub fn dst_addr(&self) -> Address {

+ 7 - 5
src/wire/icmpv4.rs

@@ -332,7 +332,7 @@ impl<'a> Repr<'a> {
     }
 
     /// Return the length of a packet that will be emitted from this high-level representation.
-    pub fn len(&self) -> usize {
+    pub fn buffer_len(&self) -> usize {
         match self {
             &Repr::EchoRequest { data, .. } |
             &Repr::EchoReply { data, .. } => {
@@ -384,10 +384,12 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
 impl<'a> fmt::Display for Repr<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            &Repr::EchoRequest { ident, seq_no, .. } =>
-                write!(f, "ICMPv4 Echo Request id={} seq={}", ident, seq_no),
-            &Repr::EchoReply { ident, seq_no, .. } =>
-                write!(f, "ICMPv4 Echo Reply id={} seq={}", ident, seq_no),
+            &Repr::EchoRequest { ident, seq_no, data } =>
+                write!(f, "ICMPv4 Echo Request id={} seq={} len={}",
+                       ident, seq_no, data.len()),
+            &Repr::EchoReply { ident, seq_no, data } =>
+                write!(f, "ICMPv4 Echo Reply id={} seq={} len={}",
+                       ident, seq_no, data.len()),
             &Repr::__Nonexhaustive => unreachable!()
         }
     }

+ 6 - 0
src/wire/ipv4.rs

@@ -382,6 +382,12 @@ impl Repr {
         })
     }
 
+    /// Return the length of a header that will be emitted from this high-level representation.
+    pub fn buffer_len(&self) -> usize {
+        // We never emit any options.
+        field::DST_ADDR.end
+    }
+
     /// Emit a high-level representation into an Internet Protocol version 4 packet.
     pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, packet: &mut Packet<T>,
                                               payload_len: usize) {

+ 1 - 1
src/wire/udp.rs

@@ -197,7 +197,7 @@ impl<'a> Repr<'a> {
     }
 
     /// Return the length of a packet that will be emitted from this high-level representation.
-    pub fn len(&self) -> usize {
+    pub fn buffer_len(&self) -> usize {
         field::CHECKSUM.end + self.payload.len()
     }