Skip to content

Commit bc2a894

Browse files
committedAug 22, 2017
Rework responses to TCP packets and factor in RST replies to TcpSocket.
1 parent 7e6e379 commit bc2a894

File tree

4 files changed

+142
-99
lines changed

4 files changed

+142
-99
lines changed
 

Diff for: ‎src/iface/ethernet.rs

+65-85
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ enum Response<'a> {
2727
Nop,
2828
Arp(ArpRepr),
2929
Icmpv4(Ipv4Repr, Icmpv4Repr<'a>),
30-
Tcpv4(Ipv4Repr, TcpRepr<'a>)
30+
Tcp(IpRepr, TcpRepr<'a>)
3131
}
3232

3333
impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
@@ -220,10 +220,10 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
220220
match ipv4_repr.protocol {
221221
IpProtocol::Icmp =>
222222
Self::process_icmpv4(ipv4_repr, ipv4_packet.payload()),
223-
IpProtocol::Tcp =>
224-
Self::process_tcpv4(sockets, timestamp, ipv4_repr, ipv4_packet.payload()),
225223
IpProtocol::Udp =>
226224
Self::process_udpv4(sockets, timestamp, ipv4_repr, ipv4_packet.payload()),
225+
IpProtocol::Tcp =>
226+
Self::process_tcp(sockets, timestamp, ipv4_repr.into(), ipv4_packet.payload()),
227227
_ if handled_by_raw_socket =>
228228
Ok(Response::Nop),
229229
_ => {
@@ -307,11 +307,9 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
307307
Ok(Response::Icmpv4(ipv4_reply_repr, icmp_reply_repr))
308308
}
309309

310-
fn process_tcpv4<'frame>(sockets: &mut SocketSet, timestamp: u64,
311-
ipv4_repr: Ipv4Repr, ip_payload: &'frame [u8]) ->
312-
Result<Response<'frame>> {
313-
let ip_repr = IpRepr::Ipv4(ipv4_repr);
314-
310+
fn process_tcp<'frame>(sockets: &mut SocketSet, timestamp: u64,
311+
ip_repr: IpRepr, ip_payload: &'frame [u8]) ->
312+
Result<Response<'frame>> {
315313
for tcp_socket in sockets.iter_mut().filter_map(
316314
<Socket as AsSocket<TcpSocket>>::try_as_socket) {
317315
match tcp_socket.process(timestamp, &ip_repr, ip_payload) {
@@ -327,99 +325,81 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
327325

328326
// The packet wasn't handled by a socket, send a TCP RST packet.
329327
let tcp_packet = TcpPacket::new_checked(ip_payload)?;
330-
if tcp_packet.rst() {
331-
// Don't reply to a TCP RST packet with another TCP RST packet.
332-
return Ok(Response::Nop)
328+
let tcp_repr = TcpRepr::parse(&tcp_packet, &ip_repr.src_addr(), &ip_repr.dst_addr())?;
329+
if tcp_repr.control == TcpControl::Rst {
330+
// Never reply to a TCP RST packet with another TCP RST packet.
331+
Ok(Response::Nop)
332+
} else {
333+
let (ip_reply_repr, tcp_reply_repr) = TcpSocket::rst_reply(&ip_repr, &tcp_repr);
334+
Ok(Response::Tcp(ip_reply_repr, tcp_reply_repr))
333335
}
334-
let tcp_reply_repr = TcpRepr {
335-
src_port: tcp_packet.dst_port(),
336-
dst_port: tcp_packet.src_port(),
337-
control: TcpControl::Rst,
338-
push: false,
339-
seq_number: tcp_packet.ack_number(),
340-
ack_number: Some(tcp_packet.seq_number() +
341-
tcp_packet.segment_len()),
342-
window_len: 0,
343-
max_seg_size: None,
344-
payload: &[]
345-
};
346-
let ipv4_reply_repr = Ipv4Repr {
347-
src_addr: ipv4_repr.dst_addr,
348-
dst_addr: ipv4_repr.src_addr,
349-
protocol: IpProtocol::Tcp,
350-
payload_len: tcp_reply_repr.buffer_len()
351-
};
352-
Ok(Response::Tcpv4(ipv4_reply_repr, tcp_reply_repr))
353336
}
354337

355338
fn send_response(&mut self, timestamp: u64, response: Response) -> Result<()> {
356-
macro_rules! ip_response {
357-
($tx_buffer:ident, $frame:ident, $ip_repr:ident) => ({
358-
let dst_hardware_addr =
359-
match self.arp_cache.lookup(&$ip_repr.dst_addr.into()) {
360-
None => return Err(Error::Unaddressable),
361-
Some(hardware_addr) => hardware_addr
362-
};
363-
364-
let tx_len = EthernetFrame::<&[u8]>::buffer_len($ip_repr.buffer_len() +
365-
$ip_repr.payload_len);
366-
$tx_buffer = self.device.transmit(timestamp, tx_len)?;
367-
debug_assert!($tx_buffer.as_ref().len() == tx_len);
339+
macro_rules! emit_packet {
340+
(Ethernet, $buffer_len:expr, |$frame:ident| $code:stmt) => ({
341+
let tx_len = EthernetFrame::<&[u8]>::buffer_len($buffer_len);
342+
let mut tx_buffer = self.device.transmit(timestamp, tx_len)?;
343+
debug_assert!(tx_buffer.as_ref().len() == tx_len);
368344

369-
$frame = EthernetFrame::new(&mut $tx_buffer);
345+
let mut $frame = EthernetFrame::new(&mut tx_buffer);
370346
$frame.set_src_addr(self.hardware_addr);
371-
$frame.set_dst_addr(dst_hardware_addr);
372-
$frame.set_ethertype(EthernetProtocol::Ipv4);
373347

374-
let mut ip_packet = Ipv4Packet::new($frame.payload_mut());
375-
$ip_repr.emit(&mut ip_packet);
376-
ip_packet
348+
$code
349+
350+
Ok(())
351+
});
352+
353+
(Ip, $ip_repr:expr, |$payload:ident| $code:stmt) => ({
354+
let ip_repr = $ip_repr.lower(&self.protocol_addrs)?;
355+
match self.arp_cache.lookup(&ip_repr.dst_addr()) {
356+
None => Err(Error::Unaddressable),
357+
Some(dst_hardware_addr) => {
358+
emit_packet!(Ethernet, ip_repr.total_len(), |frame| {
359+
frame.set_dst_addr(dst_hardware_addr);
360+
match ip_repr {
361+
IpRepr::Ipv4(_) => frame.set_ethertype(EthernetProtocol::Ipv4),
362+
_ => unreachable!()
363+
}
364+
365+
ip_repr.emit(frame.payload_mut());
366+
367+
let $payload = &mut frame.payload_mut()[ip_repr.buffer_len()..];
368+
$code
369+
})
370+
}
371+
}
377372
})
378373
}
379374

380375
match response {
381-
Response::Arp(repr) => {
382-
let tx_len = EthernetFrame::<&[u8]>::buffer_len(repr.buffer_len());
383-
let mut tx_buffer = self.device.transmit(timestamp, tx_len)?;
384-
debug_assert!(tx_buffer.as_ref().len() == tx_len);
385-
386-
let mut frame = EthernetFrame::new(&mut tx_buffer);
387-
frame.set_src_addr(self.hardware_addr);
388-
frame.set_dst_addr(match repr {
389-
ArpRepr::EthernetIpv4 { target_hardware_addr, .. } => target_hardware_addr,
390-
_ => unreachable!()
391-
});
392-
frame.set_ethertype(EthernetProtocol::Arp);
376+
Response::Arp(arp_repr) => {
377+
let dst_hardware_addr =
378+
match arp_repr {
379+
ArpRepr::EthernetIpv4 { target_hardware_addr, .. } => target_hardware_addr,
380+
_ => unreachable!()
381+
};
393382

394-
let mut packet = ArpPacket::new(frame.payload_mut());
395-
repr.emit(&mut packet);
383+
emit_packet!(Ethernet, arp_repr.buffer_len(), |frame| {
384+
frame.set_dst_addr(dst_hardware_addr);
385+
frame.set_ethertype(EthernetProtocol::Arp);
396386

397-
Ok(())
387+
let mut packet = ArpPacket::new(frame.payload_mut());
388+
arp_repr.emit(&mut packet);
389+
})
398390
},
399-
400-
Response::Icmpv4(ip_repr, icmp_repr) => {
401-
let mut tx_buffer;
402-
let mut frame;
403-
let mut ip_packet = ip_response!(tx_buffer, frame, ip_repr);
404-
let mut icmp_packet = Icmpv4Packet::new(ip_packet.payload_mut());
405-
icmp_repr.emit(&mut icmp_packet);
406-
Ok(())
391+
Response::Icmpv4(ipv4_repr, icmpv4_repr) => {
392+
emit_packet!(Ip, IpRepr::Ipv4(ipv4_repr), |payload| {
393+
icmpv4_repr.emit(&mut Icmpv4Packet::new(payload));
394+
})
407395
}
408-
409-
Response::Tcpv4(ip_repr, tcp_repr) => {
410-
let mut tx_buffer;
411-
let mut frame;
412-
let mut ip_packet = ip_response!(tx_buffer, frame, ip_repr);
413-
let mut tcp_packet = TcpPacket::new(ip_packet.payload_mut());
414-
tcp_repr.emit(&mut tcp_packet,
415-
&IpAddress::Ipv4(ip_repr.src_addr),
416-
&IpAddress::Ipv4(ip_repr.dst_addr));
417-
Ok(())
418-
}
419-
420-
Response::Nop => {
421-
Ok(())
396+
Response::Tcp(ip_repr, tcp_repr) => {
397+
emit_packet!(Ip, ip_repr, |payload| {
398+
tcp_repr.emit(&mut TcpPacket::new(payload),
399+
&ip_repr.src_addr(), &ip_repr.dst_addr());
400+
})
422401
}
402+
Response::Nop => Ok(())
423403
}
424404
}
425405

Diff for: ‎src/socket/tcp.rs

+46-8
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,10 @@ impl<'a> TcpSocket<'a> {
285285
listen_address: IpAddress::default(),
286286
local_endpoint: IpEndpoint::default(),
287287
remote_endpoint: IpEndpoint::default(),
288-
local_seq_no: TcpSeqNumber(0),
289-
remote_seq_no: TcpSeqNumber(0),
290-
remote_last_seq: TcpSeqNumber(0),
291-
remote_last_ack: TcpSeqNumber(0),
288+
local_seq_no: TcpSeqNumber::default(),
289+
remote_seq_no: TcpSeqNumber::default(),
290+
remote_last_seq: TcpSeqNumber::default(),
291+
remote_last_ack: TcpSeqNumber::default(),
292292
remote_win_len: 0,
293293
remote_mss: DEFAULT_MSS,
294294
retransmit: Retransmit::new(),
@@ -335,10 +335,10 @@ impl<'a> TcpSocket<'a> {
335335
self.listen_address = IpAddress::default();
336336
self.local_endpoint = IpEndpoint::default();
337337
self.remote_endpoint = IpEndpoint::default();
338-
self.local_seq_no = TcpSeqNumber(0);
339-
self.remote_seq_no = TcpSeqNumber(0);
340-
self.remote_last_seq = TcpSeqNumber(0);
341-
self.remote_last_ack = TcpSeqNumber(0);
338+
self.local_seq_no = TcpSeqNumber::default();
339+
self.remote_seq_no = TcpSeqNumber::default();
340+
self.remote_last_seq = TcpSeqNumber::default();
341+
self.remote_last_ack = TcpSeqNumber::default();
342342
self.remote_win_len = 0;
343343
self.remote_mss = DEFAULT_MSS;
344344
self.retransmit.reset();
@@ -681,6 +681,44 @@ impl<'a> TcpSocket<'a> {
681681
self.state = state
682682
}
683683

684+
pub(crate) fn reply(ip_repr: &IpRepr, tcp_repr: &TcpRepr) -> (IpRepr, TcpRepr<'static>) {
685+
let tcp_reply_repr = TcpRepr {
686+
src_port: tcp_repr.dst_port,
687+
dst_port: tcp_repr.src_port,
688+
control: TcpControl::None,
689+
push: false,
690+
seq_number: TcpSeqNumber(0),
691+
ack_number: None,
692+
window_len: 0,
693+
max_seg_size: None,
694+
payload: &[]
695+
};
696+
let ip_reply_repr = IpRepr::Unspecified {
697+
src_addr: ip_repr.dst_addr(),
698+
dst_addr: ip_repr.src_addr(),
699+
protocol: IpProtocol::Tcp,
700+
payload_len: tcp_reply_repr.buffer_len()
701+
};
702+
(ip_reply_repr, tcp_reply_repr)
703+
}
704+
705+
pub(crate) fn rst_reply(ip_repr: &IpRepr, tcp_repr: &TcpRepr) -> (IpRepr, TcpRepr<'static>) {
706+
debug_assert!(tcp_repr.control != TcpControl::Rst);
707+
708+
let (ip_reply_repr, mut tcp_reply_repr) = Self::reply(ip_repr, tcp_repr);
709+
710+
// See https://www.snellman.net/blog/archive/2016-02-01-tcp-rst/ for explanation
711+
// of why we sometimes send an RST and sometimes an RST|ACK
712+
tcp_reply_repr.control = TcpControl::Rst;
713+
tcp_reply_repr.seq_number = tcp_repr.ack_number.unwrap_or_default();
714+
if tcp_repr.control == TcpControl::Syn {
715+
tcp_reply_repr.ack_number = Some(tcp_repr.seq_number +
716+
tcp_repr.segment_len());
717+
}
718+
719+
(ip_reply_repr, tcp_reply_repr)
720+
}
721+
684722
pub(crate) fn process(&mut self, timestamp: u64, ip_repr: &IpRepr,
685723
payload: &[u8]) -> Result<()> {
686724
debug_assert!(ip_repr.protocol() == IpProtocol::Tcp);

Diff for: ‎src/wire/ip.rs

+17
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ pub enum IpRepr {
177177
__Nonexhaustive
178178
}
179179

180+
impl From<Ipv4Repr> for IpRepr {
181+
fn from(repr: Ipv4Repr) -> IpRepr {
182+
IpRepr::Ipv4(repr)
183+
}
184+
}
185+
180186
impl IpRepr {
181187
/// Return the protocol version.
182188
pub fn version(&self) -> Version {
@@ -323,6 +329,17 @@ impl IpRepr {
323329
unreachable!()
324330
}
325331
}
332+
333+
/// Return the total length of a packet that will be emitted from this
334+
/// high-level representation.
335+
///
336+
/// This is the same as `repr.buffer_len() + repr.payload_len()`.
337+
///
338+
/// # Panics
339+
/// This function panics if invoked on an unspecified representation.
340+
pub fn total_len(&self) -> usize {
341+
self.buffer_len() + self.payload_len()
342+
}
326343
}
327344

328345
pub mod checksum {

Diff for: ‎src/wire/tcp.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use super::ip::checksum;
99
///
1010
/// A sequence number is a monotonically advancing integer modulo 2<sup>32</sup>.
1111
/// Sequence numbers do not have a discontiguity when compared pairwise across a signed overflow.
12-
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
12+
#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
1313
pub struct SeqNumber(pub i32);
1414

1515
impl fmt::Display for SeqNumber {
@@ -275,7 +275,6 @@ impl<T: AsRef<[u8]>> Packet<T> {
275275
}
276276

277277
/// Return the length of the segment, in terms of sequence space.
278-
#[inline]
279278
pub fn segment_len(&self) -> usize {
280279
let data = self.buffer.as_ref();
281280
let mut length = data.len() - self.header_len() as usize;
@@ -695,10 +694,9 @@ impl<'a> Repr<'a> {
695694
}
696695

697696
/// Emit a high-level representation into a Transmission Control Protocol packet.
698-
pub fn emit<T: ?Sized>(&self, packet: &mut Packet<&mut T>,
699-
src_addr: &IpAddress,
700-
dst_addr: &IpAddress)
701-
where T: AsRef<[u8]> + AsMut<[u8]> {
697+
pub fn emit<T>(&self, packet: &mut Packet<&mut T>,
698+
src_addr: &IpAddress, dst_addr: &IpAddress)
699+
where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized {
702700
packet.set_src_port(self.src_port);
703701
packet.set_dst_port(self.dst_port);
704702
packet.set_seq_number(self.seq_number);
@@ -727,6 +725,16 @@ impl<'a> Repr<'a> {
727725
packet.payload_mut().copy_from_slice(self.payload);
728726
packet.fill_checksum(src_addr, dst_addr)
729727
}
728+
729+
/// Return the length of the segment, in terms of sequence space.
730+
pub fn segment_len(&self) -> usize {
731+
let mut length = self.payload.len();
732+
match self.control {
733+
Control::Syn | Control::Fin => length += 1,
734+
_ => ()
735+
}
736+
length
737+
}
730738
}
731739

732740
impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {

0 commit comments

Comments
 (0)
Please sign in to comment.