Reply with ICMP dest. unreachable or TCP RST from unused ports.
This commit is contained in:
parent
a3481537d9
commit
5a64a87dbe
|
@ -31,7 +31,7 @@ The only supported internetworking protocol is IPv4.
|
|||
* IPv4 options are **not** supported.
|
||||
* ICMPv4 header checksum is supported.
|
||||
* ICMPv4 echo requests and replies are supported.
|
||||
* ICMPv4 destination unreachable message is **not** supported.
|
||||
* ICMPv4 destination unreachable message is supported.
|
||||
* ICMPv4 parameter problem message is **not** supported.
|
||||
|
||||
### UDP layer
|
||||
|
|
|
@ -15,19 +15,16 @@ fn main() {
|
|||
let device = Tracer::<_, EthernetFrame<&[u8]>>::new(device);
|
||||
let arp_cache = SliceArpCache::new(vec![Default::default(); 8]);
|
||||
|
||||
let hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
|
||||
let mut protocol_addrs = [IpAddress::v4(192, 168, 69, 1)];
|
||||
|
||||
let listen_address = IpAddress::v4(0, 0, 0, 0);
|
||||
let endpoint = IpEndpoint::new(listen_address, 6969);
|
||||
|
||||
let udp_rx_buffer = UdpSocketBuffer::new(vec![UdpPacketBuffer::new(vec![0; 2048])]);
|
||||
let udp_tx_buffer = UdpSocketBuffer::new(vec![UdpPacketBuffer::new(vec![0; 2048])]);
|
||||
let endpoint = IpEndpoint::new(IpAddress::default(), 6969);
|
||||
let udp_socket = UdpSocket::new(endpoint, udp_rx_buffer, udp_tx_buffer);
|
||||
|
||||
let mut sockets = [udp_socket];
|
||||
let hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
|
||||
let protocol_addrs = [IpAddress::v4(192, 168, 69, 1)];
|
||||
let sockets = [udp_socket];
|
||||
let mut iface = EthernetInterface::new(device, arp_cache,
|
||||
hardware_addr, &mut protocol_addrs[..], &mut sockets[..]);
|
||||
hardware_addr, protocol_addrs, sockets);
|
||||
|
||||
loop {
|
||||
match iface.poll() {
|
||||
|
|
|
@ -7,7 +7,8 @@ use wire::{EthernetAddress, EthernetProtocol, EthernetFrame};
|
|||
use wire::{ArpPacket, ArpRepr, ArpOperation};
|
||||
use wire::{IpAddress, IpProtocol};
|
||||
use wire::{Ipv4Packet, Ipv4Repr};
|
||||
use wire::{Icmpv4Packet, Icmpv4Repr};
|
||||
use wire::{Icmpv4Packet, Icmpv4Repr, Icmpv4DstUnreachable};
|
||||
use wire::{TcpPacket, TcpRepr, TcpControl};
|
||||
use socket::Socket;
|
||||
use super::{ArpCache};
|
||||
|
||||
|
@ -115,7 +116,8 @@ impl<'a, 'b: 'a,
|
|||
enum Response<'a> {
|
||||
Nop,
|
||||
Arp(ArpRepr),
|
||||
Icmpv4(Ipv4Repr, Icmpv4Repr<'a>)
|
||||
Icmpv4(Ipv4Repr, Icmpv4Repr<'a>),
|
||||
Tcpv4(Ipv4Repr, TcpRepr<'a>)
|
||||
}
|
||||
|
||||
// First, transmit any outgoing packets.
|
||||
|
@ -168,7 +170,8 @@ impl<'a, 'b: 'a,
|
|||
// Handle IP packets directed at us.
|
||||
EthernetProtocol::Ipv4 => {
|
||||
let ip_packet = try!(Ipv4Packet::new(eth_frame.payload()));
|
||||
match try!(Ipv4Repr::parse(&ip_packet)) {
|
||||
let ip_repr = try!(Ipv4Repr::parse(&ip_packet));
|
||||
match ip_repr {
|
||||
// Ignore IP packets not directed at us.
|
||||
Ipv4Repr { dst_addr, .. } if !self.has_protocol_addr(dst_addr) => (),
|
||||
|
||||
|
@ -204,16 +207,58 @@ impl<'a, 'b: 'a,
|
|||
|
||||
// Try dispatching a packet to a socket.
|
||||
Ipv4Repr { src_addr, dst_addr, protocol } => {
|
||||
let mut handled = false;
|
||||
for socket in self.sockets.borrow_mut() {
|
||||
match socket.collect(&src_addr.into(), &dst_addr.into(),
|
||||
protocol, ip_packet.payload()) {
|
||||
Ok(()) => break,
|
||||
Ok(()) => { handled = true; break }
|
||||
Err(Error::Rejected) => continue,
|
||||
Err(e) => return Err(e)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: respond with ICMP destination unreachable here?
|
||||
if !handled && protocol == IpProtocol::Tcp {
|
||||
let tcp_packet = try!(TcpPacket::new(ip_packet.payload()));
|
||||
|
||||
let ip_reply_repr = Ipv4Repr {
|
||||
src_addr: dst_addr,
|
||||
dst_addr: src_addr,
|
||||
protocol: IpProtocol::Tcp
|
||||
};
|
||||
let tcp_reply_repr = TcpRepr {
|
||||
src_port: tcp_packet.dst_port(),
|
||||
dst_port: tcp_packet.src_port(),
|
||||
control: TcpControl::Rst,
|
||||
seq_number: 0,
|
||||
ack_number: Some(tcp_packet.seq_number() + 1),
|
||||
window_len: 0,
|
||||
payload: &[]
|
||||
};
|
||||
response = Response::Tcpv4(ip_reply_repr, tcp_reply_repr);
|
||||
} else if !handled {
|
||||
let reason;
|
||||
if protocol == IpProtocol::Udp {
|
||||
reason = Icmpv4DstUnreachable::PortUnreachable
|
||||
} else {
|
||||
reason = Icmpv4DstUnreachable::ProtoUnreachable
|
||||
}
|
||||
|
||||
let mut data = [0; 8];
|
||||
data.copy_from_slice(&ip_packet.payload()[0..8]);
|
||||
|
||||
let ip_reply_repr = Ipv4Repr {
|
||||
src_addr: dst_addr,
|
||||
dst_addr: src_addr,
|
||||
protocol: IpProtocol::Icmp
|
||||
};
|
||||
let icmp_reply_repr = Icmpv4Repr::DstUnreachable {
|
||||
reason: reason,
|
||||
header: ip_repr,
|
||||
length: ip_packet.payload().len(),
|
||||
data: data
|
||||
};
|
||||
response = Response::Icmpv4(ip_reply_repr, icmp_reply_repr)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -222,6 +267,29 @@ impl<'a, 'b: 'a,
|
|||
_ => return Err(Error::Unrecognized)
|
||||
}
|
||||
|
||||
macro_rules! ip_response {
|
||||
($tx_buffer:ident, $frame:ident, $ip_repr:ident, $length:expr) => ({
|
||||
let dst_hardware_addr =
|
||||
match self.arp_cache.lookup($ip_repr.dst_addr.into()) {
|
||||
None => return Err(Error::Unaddressable),
|
||||
Some(hardware_addr) => hardware_addr
|
||||
};
|
||||
|
||||
let payload_len = $length;
|
||||
let frame_len = EthernetFrame::<&[u8]>::buffer_len($ip_repr.buffer_len() +
|
||||
payload_len);
|
||||
$tx_buffer = try!(self.device.transmit(frame_len));
|
||||
$frame = try!(EthernetFrame::new(&mut $tx_buffer));
|
||||
$frame.set_src_addr(self.hardware_addr);
|
||||
$frame.set_dst_addr(dst_hardware_addr);
|
||||
$frame.set_ethertype(EthernetProtocol::Ipv4);
|
||||
|
||||
let mut ip_packet = try!(Ipv4Packet::new($frame.payload_mut()));
|
||||
$ip_repr.emit(&mut ip_packet, payload_len);
|
||||
ip_packet
|
||||
})
|
||||
}
|
||||
|
||||
match response {
|
||||
Response::Arp(repr) => {
|
||||
let tx_len = EthernetFrame::<&[u8]>::buffer_len(repr.buffer_len());
|
||||
|
@ -241,26 +309,24 @@ impl<'a, 'b: 'a,
|
|||
},
|
||||
|
||||
Response::Icmpv4(ip_repr, icmp_repr) => {
|
||||
let dst_hardware_addr =
|
||||
match self.arp_cache.lookup(ip_repr.dst_addr.into()) {
|
||||
None => return Err(Error::Unaddressable),
|
||||
Some(hardware_addr) => hardware_addr
|
||||
};
|
||||
|
||||
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(EthernetProtocol::Ipv4);
|
||||
|
||||
let mut ip_packet = try!(Ipv4Packet::new(frame.payload_mut()));
|
||||
ip_repr.emit(&mut ip_packet, icmp_repr.buffer_len());
|
||||
|
||||
let mut tx_buffer;
|
||||
let mut frame;
|
||||
let mut ip_packet = ip_response!(tx_buffer, frame, ip_repr,
|
||||
icmp_repr.buffer_len());
|
||||
let mut icmp_packet = try!(Icmpv4Packet::new(ip_packet.payload_mut()));
|
||||
icmp_repr.emit(&mut icmp_packet);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Response::Tcpv4(ip_repr, tcp_repr) => {
|
||||
let mut tx_buffer;
|
||||
let mut frame;
|
||||
let mut ip_packet = ip_response!(tx_buffer, frame, ip_repr,
|
||||
tcp_repr.buffer_len());
|
||||
let mut tcp_packet = try!(TcpPacket::new(ip_packet.payload_mut()));
|
||||
tcp_repr.emit(&mut tcp_packet,
|
||||
&IpAddress::Ipv4(ip_repr.src_addr),
|
||||
&IpAddress::Ipv4(ip_repr.dst_addr));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use core::cmp;
|
||||
use core::fmt;
|
||||
use byteorder::{ByteOrder, NetworkEndian};
|
||||
|
||||
|
@ -100,9 +99,7 @@ impl<T: AsRef<[u8]>> Frame<T> {
|
|||
/// 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)
|
||||
field::PAYLOAD.start + payload_len
|
||||
}
|
||||
|
||||
/// Return the destination address field.
|
||||
|
|
|
@ -3,6 +3,7 @@ use byteorder::{ByteOrder, NetworkEndian};
|
|||
|
||||
use Error;
|
||||
use super::ip::checksum;
|
||||
use super::{Ipv4Packet, Ipv4Repr};
|
||||
|
||||
enum_with_unknown! {
|
||||
/// Internet protocol control message type.
|
||||
|
@ -10,7 +11,7 @@ enum_with_unknown! {
|
|||
/// Echo reply
|
||||
EchoReply = 0,
|
||||
/// Destination unreachable
|
||||
DstUnreachable = 1,
|
||||
DstUnreachable = 3,
|
||||
/// Message redirect
|
||||
Redirect = 5,
|
||||
/// Echo request
|
||||
|
@ -86,6 +87,47 @@ enum_with_unknown! {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for DstUnreachable {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&DstUnreachable::NetUnreachable =>
|
||||
write!(f, "destination network unreachable"),
|
||||
&DstUnreachable::HostUnreachable =>
|
||||
write!(f, "destination host unreachable"),
|
||||
&DstUnreachable::ProtoUnreachable =>
|
||||
write!(f, "destination protocol unreachable"),
|
||||
&DstUnreachable::PortUnreachable =>
|
||||
write!(f, "destination port unreachable"),
|
||||
&DstUnreachable::FragRequired =>
|
||||
write!(f, "fragmentation required, and DF flag set"),
|
||||
&DstUnreachable::SrcRouteFailed =>
|
||||
write!(f, "source route failed"),
|
||||
&DstUnreachable::DstNetUnknown =>
|
||||
write!(f, "destination network unknown"),
|
||||
&DstUnreachable::DstHostUnknown =>
|
||||
write!(f, "destination host unknown"),
|
||||
&DstUnreachable::SrcHostIsolated =>
|
||||
write!(f, "source host isolated"),
|
||||
&DstUnreachable::NetProhibited =>
|
||||
write!(f, "network administratively prohibited"),
|
||||
&DstUnreachable::HostProhibited =>
|
||||
write!(f, "host administratively prohibited"),
|
||||
&DstUnreachable::NetUnreachToS =>
|
||||
write!(f, "network unreachable for ToS"),
|
||||
&DstUnreachable::HostUnreachToS =>
|
||||
write!(f, "host unreachable for ToS"),
|
||||
&DstUnreachable::CommProhibited =>
|
||||
write!(f, "communication administratively prohibited"),
|
||||
&DstUnreachable::HostPrecedViol =>
|
||||
write!(f, "host precedence violation"),
|
||||
&DstUnreachable::PrecedCutoff =>
|
||||
write!(f, "precedence cutoff in effect"),
|
||||
&DstUnreachable::Unknown(id) =>
|
||||
write!(f, "{}", id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum_with_unknown! {
|
||||
/// Internet protocol control message subtype for type "Redirect Message".
|
||||
pub doc enum Redirect(u8) {
|
||||
|
@ -135,6 +177,8 @@ mod field {
|
|||
pub const CODE: usize = 1;
|
||||
pub const CHECKSUM: Field = 2..4;
|
||||
|
||||
pub const UNUSED: Field = 4..8;
|
||||
|
||||
pub const ECHO_IDENT: Field = 4..6;
|
||||
pub const ECHO_SEQNO: Field = 6..8;
|
||||
}
|
||||
|
@ -206,8 +250,9 @@ impl<T: AsRef<[u8]>> Packet<T> {
|
|||
/// The result depends on the value of the message type field.
|
||||
pub fn header_len(&self) -> usize {
|
||||
match self.msg_type() {
|
||||
Message::EchoRequest => field::ECHO_SEQNO.end,
|
||||
Message::EchoReply => field::ECHO_SEQNO.end,
|
||||
Message::EchoRequest => field::ECHO_SEQNO.end,
|
||||
Message::EchoReply => field::ECHO_SEQNO.end,
|
||||
Message::DstUnreachable => field::UNUSED.end,
|
||||
_ => field::CHECKSUM.end // make a conservative assumption
|
||||
}
|
||||
}
|
||||
|
@ -304,6 +349,12 @@ pub enum Repr<'a> {
|
|||
seq_no: u16,
|
||||
data: &'a [u8]
|
||||
},
|
||||
DstUnreachable {
|
||||
reason: DstUnreachable,
|
||||
header: Ipv4Repr,
|
||||
length: usize,
|
||||
data: [u8; 8]
|
||||
},
|
||||
#[doc(hidden)]
|
||||
__Nonexhaustive
|
||||
}
|
||||
|
@ -320,6 +371,7 @@ impl<'a> Repr<'a> {
|
|||
data: packet.data()
|
||||
})
|
||||
},
|
||||
|
||||
(Message::EchoReply, 0) => {
|
||||
Ok(Repr::EchoReply {
|
||||
ident: packet.echo_ident(),
|
||||
|
@ -327,6 +379,25 @@ impl<'a> Repr<'a> {
|
|||
data: packet.data()
|
||||
})
|
||||
},
|
||||
|
||||
(Message::DstUnreachable, code) => {
|
||||
let ip_packet = try!(Ipv4Packet::new(packet.data()));
|
||||
let ip_repr = try!(Ipv4Repr::parse(&ip_packet));
|
||||
|
||||
let mut data = [0; 8];
|
||||
let payload = &packet.data()[ip_packet.header_len() as usize..];
|
||||
if payload.len() < data.len() { return Err(Error::Truncated) }
|
||||
data.copy_from_slice(&payload[0..8]);
|
||||
|
||||
let length = ip_packet.total_len() as usize - ip_packet.header_len() as usize;
|
||||
|
||||
Ok(Repr::DstUnreachable {
|
||||
reason: DstUnreachable::from(code),
|
||||
header: ip_repr,
|
||||
length: length,
|
||||
data: data
|
||||
})
|
||||
}
|
||||
_ => Err(Error::Unrecognized)
|
||||
}
|
||||
}
|
||||
|
@ -338,6 +409,9 @@ impl<'a> Repr<'a> {
|
|||
&Repr::EchoReply { data, .. } => {
|
||||
field::ECHO_SEQNO.end + data.len()
|
||||
},
|
||||
&Repr::DstUnreachable { header, data, .. } => {
|
||||
field::UNUSED.end + header.buffer_len() + data.len()
|
||||
}
|
||||
&Repr::__Nonexhaustive => unreachable!()
|
||||
}
|
||||
}
|
||||
|
@ -349,18 +423,33 @@ impl<'a> Repr<'a> {
|
|||
match self {
|
||||
&Repr::EchoRequest { ident, seq_no, data } => {
|
||||
packet.set_msg_type(Message::EchoRequest);
|
||||
packet.set_msg_code(0);
|
||||
packet.set_echo_ident(ident);
|
||||
packet.set_echo_seq_no(seq_no);
|
||||
let data_len = cmp::min(packet.data_mut().len(), data.len());
|
||||
packet.data_mut()[..data_len].copy_from_slice(&data[..data_len])
|
||||
},
|
||||
|
||||
&Repr::EchoReply { ident, seq_no, data } => {
|
||||
packet.set_msg_type(Message::EchoReply);
|
||||
packet.set_msg_code(0);
|
||||
packet.set_echo_ident(ident);
|
||||
packet.set_echo_seq_no(seq_no);
|
||||
let data_len = cmp::min(packet.data_mut().len(), data.len());
|
||||
packet.data_mut()[..data_len].copy_from_slice(&data[..data_len])
|
||||
},
|
||||
|
||||
&Repr::DstUnreachable { reason, header, length, data } => {
|
||||
packet.set_msg_type(Message::DstUnreachable);
|
||||
packet.set_msg_code(reason.into());
|
||||
|
||||
let mut ip_packet = Ipv4Packet::new(packet.data_mut())
|
||||
.expect("undersized data");
|
||||
header.emit(&mut ip_packet, length);
|
||||
let mut payload = &mut ip_packet.into_inner()[header.buffer_len()..];
|
||||
payload.copy_from_slice(&data[..])
|
||||
}
|
||||
|
||||
&Repr::__Nonexhaustive => unreachable!()
|
||||
}
|
||||
packet.fill_checksum()
|
||||
|
@ -371,10 +460,14 @@ 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),
|
||||
_ => {
|
||||
try!(write!(f, "ICMPv4 (unrecognized)"));
|
||||
try!(write!(f, " type={} code={} cksum={:#04x}",
|
||||
self.msg_type(), self.msg_code(), self.checksum()));
|
||||
Err(err) => {
|
||||
try!(write!(f, "ICMPv4 ({})", err));
|
||||
try!(write!(f, " type={:?}", self.msg_type()));
|
||||
match self.msg_type() {
|
||||
Message::DstUnreachable =>
|
||||
try!(write!(f, " code={:?}", DstUnreachable::from(self.msg_code()))),
|
||||
_ => try!(write!(f, " code={}", self.msg_code()))
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -385,11 +478,14 @@ impl<'a> fmt::Display for Repr<'a> {
|
|||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&Repr::EchoRequest { ident, seq_no, data } =>
|
||||
write!(f, "ICMPv4 Echo Request id={} seq={} len={}",
|
||||
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={}",
|
||||
write!(f, "ICMPv4 echo reply id={} seq={} len={}",
|
||||
ident, seq_no, data.len()),
|
||||
&Repr::DstUnreachable { reason, .. } =>
|
||||
write!(f, "ICMPv4 destination unreachable ({})",
|
||||
reason),
|
||||
&Repr::__Nonexhaustive => unreachable!()
|
||||
}
|
||||
}
|
||||
|
@ -400,14 +496,21 @@ use super::pretty_print::{PrettyPrint, PrettyIndent};
|
|||
impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
|
||||
fn pretty_print(buffer: &AsRef<[u8]>, f: &mut fmt::Formatter,
|
||||
indent: &mut PrettyIndent) -> fmt::Result {
|
||||
match Packet::new(buffer) {
|
||||
Err(err) => write!(f, "{}({})\n", indent, err),
|
||||
Ok(packet) => write!(f, "{}{}\n", indent, packet)
|
||||
let packet = match Packet::new(buffer) {
|
||||
Err(err) => return write!(f, "{}({})\n", indent, err),
|
||||
Ok(packet) => packet
|
||||
};
|
||||
try!(write!(f, "{}{}\n", indent, packet));
|
||||
|
||||
indent.increase();
|
||||
match packet.msg_type() {
|
||||
Message::DstUnreachable =>
|
||||
super::Ipv4Packet::<&[u8]>::pretty_print(&packet.data(), f, indent),
|
||||
_ => Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
|
|
@ -86,7 +86,7 @@ pub struct Endpoint {
|
|||
impl Endpoint {
|
||||
pub const INVALID: Endpoint = Endpoint { addr: Address::Invalid, port: 0 };
|
||||
|
||||
/// Create an internet endpoint address.
|
||||
/// Create an endpoint address from given address and port.
|
||||
pub fn new(addr: Address, port: u16) -> Endpoint {
|
||||
Endpoint { addr: addr, port: port }
|
||||
}
|
||||
|
|
|
@ -401,7 +401,7 @@ impl Repr {
|
|||
pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, packet: &mut Packet<T>,
|
||||
payload_len: usize) {
|
||||
packet.set_version(4);
|
||||
packet.set_header_len(20);
|
||||
packet.set_header_len(field::DST_ADDR.end as u8);
|
||||
packet.set_dscp(0);
|
||||
packet.set_ecn(0);
|
||||
let total_len = packet.header_len() as u16 + payload_len as u16;
|
||||
|
@ -423,8 +423,8 @@ 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),
|
||||
_ => {
|
||||
try!(write!(f, "IPv4 (unrecognized)"));
|
||||
Err(err) => {
|
||||
try!(write!(f, "IPv4 ({})", err));
|
||||
try!(write!(f, " src={} dst={} proto={} ttl={}",
|
||||
self.src_addr(), self.dst_addr(), self.protocol(), self.ttl()));
|
||||
if self.version() != 4 {
|
||||
|
@ -471,12 +471,12 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
|
|||
fn pretty_print(buffer: &AsRef<[u8]>, f: &mut fmt::Formatter,
|
||||
indent: &mut PrettyIndent) -> fmt::Result {
|
||||
let packet = match Packet::new(buffer) {
|
||||
Err(err) => return write!(f, "{}({})\n", indent, err),
|
||||
Err(err) => return write!(f, "{}({})\n", indent, err),
|
||||
Ok(packet) => packet
|
||||
};
|
||||
try!(write!(f, "{}{}\n", indent, packet));
|
||||
indent.increase();
|
||||
|
||||
indent.increase();
|
||||
match packet.protocol() {
|
||||
Protocol::Icmp =>
|
||||
super::Icmpv4Packet::<&[u8]>::pretty_print(&packet.payload(), f, indent),
|
||||
|
|
|
@ -462,7 +462,7 @@ impl<'a> Repr<'a> {
|
|||
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.set_header_len(field::URGENT.end as u8);
|
||||
packet.clear_flags();
|
||||
match self.control {
|
||||
Control::None => (),
|
||||
|
@ -470,6 +470,7 @@ impl<'a> Repr<'a> {
|
|||
Control::Fin => packet.set_fin(true),
|
||||
Control::Rst => packet.set_rst(true)
|
||||
}
|
||||
packet.set_ack(self.ack_number.is_some());
|
||||
packet.payload_mut().copy_from_slice(self.payload);
|
||||
packet.fill_checksum(src_addr, dst_addr)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue