netstack3_filter/conntrack/
tcp.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! TCP state tracking.
6
7use core::time::Duration;
8
9use netstack3_base::{Control, SegmentHeader, SeqNum, UnscaledWindowSize, WindowScale, WindowSize};
10use replace_with::replace_with_and;
11
12use super::{
13    ConnectionDirection, ConnectionUpdateAction, ConnectionUpdateError, EstablishmentLifecycle,
14};
15
16/// A struct that completely encapsulates tracking a bidirectional TCP
17/// connection.
18#[derive(Debug, Clone)]
19pub(crate) struct Connection {
20    /// The current state of the TCP connection.
21    state: State,
22}
23
24impl Connection {
25    pub fn new(segment: &SegmentHeader, payload_len: usize, self_connected: bool) -> Option<Self> {
26        Some(Self {
27            // TODO(https://fxbug.dev/355699182): Properly support self-connected
28            // connections.
29            state: if self_connected {
30                Untracked {}.into()
31            } else {
32                State::new(segment, payload_len)?
33            },
34        })
35    }
36
37    pub fn expiry_duration(&self, establishment_lifecycle: EstablishmentLifecycle) -> Duration {
38        self.state.expiry_duration(establishment_lifecycle)
39    }
40
41    pub fn update(
42        &mut self,
43        segment: &SegmentHeader,
44        payload_len: usize,
45        dir: ConnectionDirection,
46    ) -> Result<ConnectionUpdateAction, ConnectionUpdateError> {
47        let valid =
48            replace_with_and(&mut self.state, |state| state.update(segment, payload_len, dir));
49
50        if !valid {
51            return Err(ConnectionUpdateError::InvalidPacket);
52        }
53
54        match self.state {
55            State::Closed(_) => Ok(ConnectionUpdateAction::RemoveEntry),
56            State::Untracked(_)
57            | State::SynSent(_)
58            | State::WaitingOnOpeningAck(_)
59            | State::Closing(_)
60            | State::Established(_) => Ok(ConnectionUpdateAction::NoAction),
61        }
62    }
63}
64
65/// States for a TCP connection as a whole.
66///
67/// These vaguely correspond to states from RFC 9293, but since they apply to
68/// the whole connection, and we're just snooping in the middle, they can't line
69/// up perfectly 1:1. See the doc comments on each state for the expected state
70/// of each of the peers assuming that all packets are received and are valid.
71#[derive(Debug, Clone, PartialEq, Eq)]
72pub(crate) enum State {
73    /// The connection has properties that break standard state tracking. This
74    /// state does a good-enough job tracking the connection.
75    ///
76    /// This is a short-circuit state that can never be left.
77    Untracked(Untracked),
78
79    /// The connection has been closed, either by the FIN handshake or valid
80    /// RST.
81    ///
82    /// This is a short-circuit state that can never be left.
83    Closed(Closed),
84
85    /// The initial SYN for this connection has been sent. State contained
86    /// within is everything that can be gleaned from the initial SYN packet
87    /// sent in the original direction.
88    ///
89    /// Expected peer states:
90    /// - Original: `SYN_SENT`
91    /// - Reply: `SYN_RECEIVED` (upon receipt)
92    SynSent(SynSent),
93
94    /// The reply peer has sent a valid SYN/ACK segment. All that remains is for
95    /// the original peer to ACK.
96    ///
97    /// Expected peer states.
98    /// - Original: ESTABLISHED
99    /// - Reply: SYN_RECEIVED
100    WaitingOnOpeningAck(WaitingOnOpeningAck),
101
102    /// The handshake has completed and data may begin flowing at any time. This
103    /// is where most connections will spend the vast majority of their time.
104    ///
105    /// Expected peer states:
106    /// - Original: ESTABLISHED
107    /// - Reply: ESTABLISHED
108    Established(Established),
109
110    /// The process of closing down a connection starting from when the first
111    /// FIN is seen and until FINs from both peers have been ACKed.
112    ///
113    /// Expected peer states are any of:
114    /// - FIN_WAIT_1
115    /// - FIN_WAIT_2
116    /// - CLOSING
117    /// - CLOSE_WAIT
118    /// - LAST_ACK
119    Closing(Closing),
120}
121
122impl State {
123    fn new(segment: &SegmentHeader, payload_len: usize) -> Option<Self> {
124        // We explicitly don't want to track any connections that we haven't
125        // seen from the beginning because:
126        //
127        // a) This shouldn't happen, since we run from boot
128        // b) Window scale is only negotiated during the initial handshake.
129        match segment.control {
130            Some(Control::SYN) => {}
131            None | Some(Control::FIN) | Some(Control::RST) => return None,
132        }
133
134        Some(
135            SynSent {
136                iss: segment.seq,
137                logical_len: segment.len(payload_len),
138                advertised_window_scale: segment.options.window_scale(),
139                // This unwrap cannot fail because WindowSize::MAX is 2^30-1,
140                // which is larger than the largest possible unscaled window
141                // size (2^16).
142                window_size: WindowSize::from_u32(u16::from(segment.wnd).into()).unwrap(),
143            }
144            .into(),
145        )
146    }
147
148    fn expiry_duration(&self, establishment_lifecycle: EstablishmentLifecycle) -> Duration {
149        const MAXIMUM_SEGMENT_LIFETIME: Duration = Duration::from_secs(120);
150
151        // These are all picked to optimize purging connections from the table
152        // as soon as is reasonable. Unlike Linux, we are choosing to be more
153        // conservative with our timeouts and setting the most aggressive one to
154        // the standard MSL of 120 seconds.
155        match self {
156            State::Untracked(_) => {
157                match establishment_lifecycle {
158                    // This is small because it's just meant to be the time for
159                    // the initial handshake.
160                    EstablishmentLifecycle::SeenOriginal | EstablishmentLifecycle::SeenReply => {
161                        MAXIMUM_SEGMENT_LIFETIME
162                    }
163                    EstablishmentLifecycle::Established => Duration::from_secs(6 * 60 * 60),
164                }
165            }
166            State::Closed(_) => Duration::ZERO,
167            State::SynSent(_) => MAXIMUM_SEGMENT_LIFETIME,
168            State::WaitingOnOpeningAck(_) => MAXIMUM_SEGMENT_LIFETIME,
169            State::Established(Established { original, reply }) => {
170                // If there is no data outstanding, make the timeout large, and
171                // otherwise small so we can purge the connection quickly if one
172                // of the endpoints disappears.
173                if original.unacked_data || reply.unacked_data {
174                    MAXIMUM_SEGMENT_LIFETIME
175                } else {
176                    Duration::from_secs(5 * 60 * 60 * 24)
177                }
178            }
179            State::Closing(_) => MAXIMUM_SEGMENT_LIFETIME,
180        }
181    }
182
183    /// Returns a new state that unconditionally replaces the previous one. The
184    /// boolean represents whether the segment was valid or not.
185    ///
186    /// In the case where the segment was invalid, the returned state will be
187    /// equivalent to the one that `update` was called on.
188    fn update(
189        self,
190        segment: &SegmentHeader,
191        payload_len: usize,
192        dir: ConnectionDirection,
193    ) -> (State, bool) {
194        match self {
195            State::Untracked(s) => s.update(segment, payload_len, dir),
196            State::Closed(s) => s.update(segment, payload_len, dir),
197            State::SynSent(s) => s.update(segment, payload_len, dir),
198            State::WaitingOnOpeningAck(s) => s.update(segment, payload_len, dir),
199            State::Established(s) => s.update(segment, payload_len, dir),
200            State::Closing(s) => s.update(segment, payload_len, dir),
201        }
202    }
203}
204
205macro_rules! state_from_state_struct {
206    ($struct:ident) => {
207        impl From<$struct> for State {
208            fn from(value: $struct) -> Self {
209                Self::$struct(value)
210            }
211        }
212    };
213}
214
215/// Contains all of the information required for a single peer in an established
216/// TCP connection.
217///
218/// Packets are valid with the following equations (taken from ["Real Stateful
219/// TCP Packet Filtering in IP Filter"][paper] and updated to allow for segments
220/// intersecting the valid ranges, rather than needing to be entirely contained
221/// within them).
222///
223/// Definitions:
224/// - s: The sequence number of the first octet of the segment
225/// - n: The (virtual) length of the segment in octets
226/// - a: The ACK number of the segment
227///
228/// I:   Data upper bound: s   <= receiver.max_wnd_seq
229/// II:  Data lower bound: s+n >= sender.max_next_seq - receiver.max_wnd
230/// III: ACK  upper bound: a   <= receiver.max_next_seq
231/// IV:  ACK  lower bound: a   >= receiver.max_next_seq - MAXACKWINDOW
232///
233/// MAXACKWINDOW is defined in the paper to be 66000, which is larger than
234/// the largest possible window (without scaling). We scale by
235/// sender.window_scale to ensure this property remains true.
236///
237/// [paper]: https://www.usenix.org/legacy/events/sec01/invitedtalks/rooij.pdf
238#[derive(Debug, Clone, PartialEq, Eq)]
239struct Peer {
240    /// How much to scale window updates from this peer.
241    window_scale: WindowScale,
242
243    /// The maximum window size ever sent by this peer.
244    ///
245    /// On every packet sent by this peer, the larger of itself and the
246    /// (scaled) window from the packet is taken.
247    max_wnd: WindowSize,
248
249    /// The maximum sequence number that is in the window for this peer.
250    ///
251    /// On every packet sent by this peer, this is updated to be the larger of
252    /// itself or the current advertised window (scaled) plus the ACK number in
253    /// the packet.
254    max_wnd_seq: SeqNum,
255
256    /// The largest "next octet" ever sent by this peer. This is equivalent to
257    /// one more than the largest sequence number ever sent by this peer.
258    ///
259    /// On every packet sent by this peer, this is updated to be the larger of
260    /// itself or the sequence number plus the length of the packet.
261    max_next_seq: SeqNum,
262
263    /// Has this peer sent data that has yet to be ACKed?
264    ///
265    /// Set when max_next_seq is increased.
266    ///
267    /// Unset when a reply segment is seen that has an ACK number equal to
268    /// `max_next_seq` (larger would mean an invalid packet).
269    unacked_data: bool,
270
271    /// The state of the first FIN segment sent by this peer.
272    fin_state: FinState,
273}
274
275impl Peer {
276    /// Checks that an ACK segment is within the windows defined in the comment on [`Peer`].
277    fn ack_segment_valid(
278        sender: &Self,
279        receiver: &Self,
280        seq: SeqNum,
281        len: u32,
282        ack: SeqNum,
283    ) -> bool {
284        // All checks below are for the negation of the equation referenced in
285        // the associated comment.
286
287        // I: Segment sequence numbers upper bound.
288        if seq.after(receiver.max_wnd_seq) {
289            return false;
290        }
291
292        // II: Segment sequence numbers lower bound.
293        if (seq + len).before(sender.max_next_seq - receiver.max_wnd) {
294            return false;
295        }
296
297        // III: ACK upper bound.
298        if ack.after(receiver.max_next_seq) {
299            return false;
300        }
301
302        // IV: ACK lower bound.
303        if ack.before(receiver.max_next_seq - receiver.max_ack_window()) {
304            return false;
305        }
306
307        true
308    }
309
310    /// Returns a new `Peer` updated using the provided information from a
311    /// segment which it has sent.
312    fn update_sender(
313        self,
314        seq: SeqNum,
315        len: u32,
316        ack: SeqNum,
317        wnd: UnscaledWindowSize,
318        fin_seen: bool,
319    ) -> Self {
320        let Self { window_scale, max_wnd, max_wnd_seq, max_next_seq, unacked_data, fin_state } =
321            self;
322
323        // The minimum window size is assumed to be 1. From the paper:
324        //   On BSD systems, a window probing is always done with a packet
325        //   containing one octet of data.
326        let window_size = {
327            let window_size = wnd << window_scale;
328            // The unwrap below won't fail because 1 is less than
329            // WindowSize::MAX.
330            core::cmp::max(window_size, WindowSize::from_u32(1).unwrap())
331        };
332
333        // The largest sequence number allowed by the current window.
334        let wnd_seq = ack + window_size;
335        // The octet one past the last one in the segment.
336        let end = seq + len;
337        // The largest `end` value sent by this peer.
338        let sender_max_next_seq = if max_next_seq.before(end) { end } else { max_next_seq };
339
340        Peer {
341            window_scale,
342            max_wnd: core::cmp::max(max_wnd, window_size),
343            max_wnd_seq: if max_wnd_seq.before(wnd_seq) { wnd_seq } else { max_wnd_seq },
344            max_next_seq: sender_max_next_seq,
345            unacked_data: if sender_max_next_seq.after(max_next_seq) { true } else { unacked_data },
346            fin_state: if fin_seen { fin_state.update_fin_sent(end - 1) } else { fin_state },
347        }
348    }
349
350    /// Returns a new `Peer` updated using the provided information from a
351    /// segment which it received.
352    fn update_receiver(self, ack: SeqNum) -> Self {
353        let Self { window_scale, max_wnd, max_wnd_seq, max_next_seq, unacked_data, fin_state } =
354            self;
355
356        Peer {
357            window_scale,
358            max_wnd,
359            max_wnd_seq,
360            max_next_seq,
361            // It's not possible for ack to be > self.max_next_seq due to
362            // equation III, which is checked on every segment.
363            unacked_data: if ack == max_next_seq { false } else { unacked_data },
364            fin_state: fin_state.update_ack_received(ack),
365        }
366    }
367
368    fn max_ack_window(&self) -> u32 {
369        // The paper gives 66000 as the MAXACKWINDOW constant because it's a
370        // little larger than the largest possible TCP window. With winow
371        // scaling in effect, this constant is no longer valid, so we scale it
372        // up by that scaling factor.
373        //
374        // This shift is guaranteed to never overflow because the maximum value
375        // for self.window_scale is 14 and 66000 << 14 < u32::MAX.
376        66000u32 << (self.window_scale.get() as u32)
377    }
378}
379
380/// Tracks the state of the FIN process for a peer.
381#[derive(Debug, Clone, PartialEq, Eq)]
382enum FinState {
383    /// This peer has not sent a FIN yet.
384    NotSent,
385
386    /// This peer has sent a FIN with the provided sequence number.
387    ///
388    /// Updated to ensure it is the sequence number of the first FIN sent.
389    Sent(SeqNum),
390
391    /// The FIN sent by this peer has been ACKed.
392    Acked,
393}
394
395impl FinState {
396    /// To be called when the peer has sent a FIN segment with the sequence
397    /// number of the FIN.
398    ///
399    /// Returns an updated `FinState`.
400    fn update_fin_sent(self, seq: SeqNum) -> Self {
401        match self {
402            FinState::NotSent => FinState::Sent(seq),
403            FinState::Sent(s) => {
404                // NOTE: We want to track the first FIN in the sequence
405                // space, not the first one we saw.
406                if s.before(seq) { FinState::Sent(s) } else { FinState::Sent(seq) }
407            }
408            FinState::Acked => FinState::Acked,
409        }
410    }
411
412    /// To be called when the peer has received an ACK.
413    ///
414    /// Returns an updated `FinState`.
415    fn update_ack_received(self, ack: SeqNum) -> Self {
416        match self {
417            FinState::NotSent => FinState::NotSent,
418            FinState::Sent(seq) => {
419                if ack.after(seq) {
420                    FinState::Acked
421                } else {
422                    FinState::Sent(seq)
423                }
424            }
425            FinState::Acked => FinState::Acked,
426        }
427    }
428
429    /// Has this FIN been acked?
430    fn acked(&self) -> bool {
431        match self {
432            FinState::NotSent => false,
433            FinState::Sent(_) => false,
434            FinState::Acked => true,
435        }
436    }
437}
438
439/// The return value from [`do_established_update`] indicating further action.
440#[derive(Debug, PartialEq, Eq)]
441enum EstablishedUpdateResult {
442    /// The update was successful.
443    ///
444    /// `new_original` and `new_reply` are the updated versions of the original
445    /// and reply peers that were provided to the function.
446    Success { new_original: Peer, new_reply: Peer, fin_seen: bool },
447
448    /// A valid RST was seen.
449    Reset,
450
451    /// The segment was invalid.
452    ///
453    /// Includes the non-updated peers so the state can be reset.
454    Invalid { original: Peer, reply: Peer },
455}
456
457fn swap_peers(original: Peer, reply: Peer, dir: ConnectionDirection) -> (Peer, Peer) {
458    match dir {
459        ConnectionDirection::Original => (original, reply),
460        ConnectionDirection::Reply => (reply, original),
461    }
462}
463
464/// Holds and names the peers passed into [`do_established_update`] to avoid
465/// ambiguous argument order.
466struct UpdatePeers {
467    original: Peer,
468    reply: Peer,
469}
470
471/// The core functionality for handling segments once the handshake is complete.
472///
473/// Validates that segments fall within the bounds described in the comment on
474/// [`Peer`].
475fn do_established_update(
476    UpdatePeers { original, reply }: UpdatePeers,
477    segment: &SegmentHeader,
478    payload_len: usize,
479    dir: ConnectionDirection,
480) -> EstablishedUpdateResult {
481    let logical_len = segment.len(payload_len);
482    let SegmentHeader { seq, ack, wnd, control, options: _, push: _ } = segment;
483
484    let (sender, receiver) = swap_peers(original, reply, dir);
485
486    // From RFC 9293:
487    //   If the ACK control bit is set, this field contains the value of the
488    //   next sequence number the sender of the segment is expecting to receive.
489    //   Once a connection is established, this is always sent.
490    let ack = match ack {
491        Some(ack) => ack,
492        None => {
493            let (original, reply) = swap_peers(sender, receiver, dir);
494            return EstablishedUpdateResult::Invalid { original, reply };
495        }
496    };
497
498    if !Peer::ack_segment_valid(&sender, &receiver, *seq, logical_len, *ack) {
499        let (original, reply) = swap_peers(sender, receiver, dir);
500        return EstablishedUpdateResult::Invalid { original, reply };
501    }
502
503    let fin_seen = match control {
504        Some(Control::SYN) => {
505            let (original, reply) = swap_peers(sender, receiver, dir);
506            return EstablishedUpdateResult::Invalid { original, reply };
507        }
508        Some(Control::RST) => return EstablishedUpdateResult::Reset,
509        Some(Control::FIN) => true,
510        None => false,
511    };
512
513    let new_sender = sender.update_sender(*seq, logical_len, *ack, *wnd, fin_seen);
514    let new_receiver = receiver.update_receiver(*ack);
515
516    let (new_original, new_reply) = swap_peers(new_sender, new_receiver, dir);
517    EstablishedUpdateResult::Success { new_original, new_reply, fin_seen }
518}
519
520/// State for the Untracked state.
521///
522/// This state never transitions to another state.
523#[derive(Debug, Clone, PartialEq, Eq)]
524pub(crate) struct Untracked {}
525state_from_state_struct!(Untracked);
526
527impl Untracked {
528    fn update(
529        self,
530        _segment: &SegmentHeader,
531        _payload_len: usize,
532        _dir: ConnectionDirection,
533    ) -> (State, bool) {
534        (Self {}.into(), true)
535    }
536}
537
538/// State for the Closed state.
539///
540/// This state never transitions to another state.
541#[derive(Debug, Clone, PartialEq, Eq)]
542pub(crate) struct Closed {}
543state_from_state_struct!(Closed);
544
545impl Closed {
546    fn update(
547        self,
548        _segment: &SegmentHeader,
549        _payload_len: usize,
550        _dir: ConnectionDirection,
551    ) -> (State, bool) {
552        (self.into(), true)
553    }
554}
555
556/// State for the SynSent state.
557///
558/// State transitions for in-range segments by direction:
559/// - Original
560///   - SYN: Update data, stay in SynSent
561///   - SYN/ACK: Invalid
562///   - RST: Invalid
563///   - FIN: Invalid
564///   - ACK: Invalid
565/// - Reply
566///   - SYN: Untracked, until we support simultaneous open.
567///   - SYN/ACK: WaitingOnOpeningAck
568///   - RST: Delete connection
569///   - FIN: Invalid
570///   - ACK: Invalid
571#[derive(Debug, Clone, PartialEq, Eq)]
572pub(crate) struct SynSent {
573    /// The ISS (initial send sequence number) for the original TCP stack.
574    iss: SeqNum,
575
576    /// The logical length of the segment sent by the original TCP stack.
577    logical_len: u32,
578
579    /// The window scale (if set in the initial SYN) for the original TCP stack.
580    advertised_window_scale: Option<WindowScale>,
581
582    /// The window size of the original TCP stack. Will be converted into a
583    /// sequence number once we know what the reply stack's ISN is.
584    ///
585    /// RFC 1323 2.2:
586    ///   The Window field in a SYN (i.e., a <SYN> or <SYN,ACK>) segment itself
587    ///   is never scaled.
588    window_size: WindowSize,
589}
590state_from_state_struct!(SynSent);
591
592impl SynSent {
593    fn update(
594        self,
595        segment: &SegmentHeader,
596        payload_len: usize,
597        dir: ConnectionDirection,
598    ) -> (State, bool) {
599        let Self { iss, logical_len, advertised_window_scale, window_size } = self;
600
601        match dir {
602            // This is another packet in the same direction as the first one.
603            // Update existing parameters for initial SYN, but only for packets
604            // that look to be valid retransmits of the initial SYN. This
605            // behavior is copied over from gVisor.
606            ConnectionDirection::Original => {
607                if let Some(_) = segment.ack {
608                    return (self.into(), false);
609                }
610
611                match segment.control {
612                    None | Some(Control::FIN) | Some(Control::RST) => {
613                        return (self.into(), false);
614                    }
615                    Some(Control::SYN) => {}
616                };
617
618                if segment.seq != iss || segment.options.window_scale() != advertised_window_scale {
619                    return (self.into(), false);
620                }
621
622                // If it's a valid retransmit of the original SYN, update
623                // any state that changed and let it through.
624                let seg_window_size = WindowSize::from_u32(u16::from(segment.wnd).into()).unwrap();
625
626                (
627                    SynSent {
628                        iss: iss,
629                        logical_len: u32::max(segment.len(payload_len), logical_len),
630                        advertised_window_scale: advertised_window_scale,
631                        window_size: core::cmp::max(seg_window_size, window_size),
632                    }
633                    .into(),
634                    true,
635                )
636            }
637
638            ConnectionDirection::Reply => {
639                // RFC 9293 3.10.7.3:
640                //   If SND.UNA < SEG.ACK =< SND.NXT, then the ACK is
641                //   acceptable.
642                match segment.ack {
643                    None => {}
644                    Some(ack) => {
645                        if !(ack.after(iss) && ack.before(iss + logical_len + 1)) {
646                            return (self.into(), false);
647                        }
648                    }
649                };
650
651                match segment.control {
652                    None | Some(Control::FIN) => (self.into(), false),
653                    // RFC 9293 3.10.7.3:
654                    //   If the RST bit is set,
655                    //   If the ACK was acceptable, then signal to the user
656                    //   "error: connection reset", drop the segment, enter
657                    //   CLOSED state, delete TCB, and return. Otherwise (no
658                    //   ACK), drop the segment and return.
659                    //
660                    // For our purposes, we delete the connection because we
661                    // know the receiver will tear down the connection.
662                    Some(Control::RST) => match segment.ack {
663                        None => (self.into(), false),
664                        Some(_) => (Closed {}.into(), true),
665                    },
666
667                    Some(Control::SYN) => {
668                        let Some(ack) = segment.ack else {
669                            // TODO(https://fxbug.dev/355200767): Support
670                            // simultaneous open.
671                            log::warn!(
672                                "Unsupported TCP simultaneous open. Giving up on detailed tracking"
673                            );
674
675                            return (Untracked {}.into(), true);
676                        };
677
678                        let reply_window_scale = segment.options.window_scale();
679                        let reply_window_size =
680                            WindowSize::from_u32(u16::from(segment.wnd).into()).unwrap();
681
682                        // RFC 1323 2.2:
683                        //   This option is an offer, not a promise; both sides
684                        //   must send Window Scale options in their SYN
685                        //   segments to enable window scaling in either
686                        //   direction.
687                        let (original_window_scale, reply_window_scale) =
688                            match (advertised_window_scale, reply_window_scale) {
689                                (Some(original), Some(reply)) => (original, reply),
690                                _ => (WindowScale::ZERO, WindowScale::ZERO),
691                            };
692
693                        let original_max_next_seq = iss + logical_len;
694
695                        (
696                            WaitingOnOpeningAck {
697                                original: Peer {
698                                    window_scale: original_window_scale,
699                                    max_wnd: window_size,
700                                    // We're still waiting on an ACK from
701                                    // the original stack, so this is
702                                    // slightly different from the normal
703                                    // calculation. It's still valid because
704                                    // we can assume that the implicit ACK
705                                    // number is the reply ISS (no data
706                                    // ACKed).
707                                    max_wnd_seq: segment.seq + window_size,
708                                    max_next_seq: original_max_next_seq,
709                                    unacked_data: ack.before(original_max_next_seq),
710                                    fin_state: FinState::NotSent,
711                                },
712                                reply: Peer {
713                                    window_scale: reply_window_scale,
714                                    max_wnd: reply_window_size,
715                                    max_wnd_seq: ack + reply_window_size,
716                                    max_next_seq: segment.seq + segment.len(payload_len),
717                                    // The reply peer will always have
718                                    // unacked data here because the SYN we
719                                    // just saw sent needs to be acked.
720                                    unacked_data: true,
721                                    fin_state: FinState::NotSent,
722                                },
723                            }
724                            .into(),
725                            true,
726                        )
727                    }
728                }
729            }
730        }
731    }
732}
733
734/// State for the WaitingOnOpeningAck state.
735///
736/// Note this expects the ACK to come from the original direction.
737///
738/// State transitions for in-range segments by direction:
739/// - Original
740///   - SYN: Invalid
741///   - RST: Delete connection
742///   - FIN: Closing
743///   - ACK: Established
744/// - Reply
745///   - SYN: Invalid
746///   - RST: Delete connection
747///   - FIN: Closing
748///   - ACK: WaitingOnOpeningAck
749#[derive(Debug, Clone, PartialEq, Eq)]
750pub(crate) struct WaitingOnOpeningAck {
751    /// State for the "original" TCP stack (the one that we first saw a packet
752    /// for).
753    original: Peer,
754
755    /// State for the "reply" TCP stack.
756    reply: Peer,
757}
758state_from_state_struct!(WaitingOnOpeningAck);
759
760impl WaitingOnOpeningAck {
761    fn update(
762        self,
763        segment: &SegmentHeader,
764        payload_len: usize,
765        dir: ConnectionDirection,
766    ) -> (State, bool) {
767        let Self { original, reply } = self;
768
769        let (original, reply, fin_seen) = match do_established_update(
770            UpdatePeers { original, reply },
771            segment,
772            payload_len,
773            dir.clone(),
774        ) {
775            EstablishedUpdateResult::Success { new_original, new_reply, fin_seen } => {
776                (new_original, new_reply, fin_seen)
777            }
778            EstablishedUpdateResult::Invalid { original, reply } => {
779                return (Self { original, reply }.into(), false);
780            }
781            EstablishedUpdateResult::Reset => return (Closed {}.into(), true),
782        };
783
784        let new_state = if fin_seen {
785            Closing { original, reply }.into()
786        } else {
787            match dir {
788                // We move to Established because we know that if the ACK was
789                // valid (checked by do_established_update), the ACK must
790                // include the SYN, which is the first possible octet.
791                ConnectionDirection::Original => Established { original, reply }.into(),
792                ConnectionDirection::Reply => WaitingOnOpeningAck { original, reply }.into(),
793            }
794        };
795
796        (new_state, true)
797    }
798}
799
800/// State for the Established state.
801///
802/// State transitions for in-range segments, regardless of direction:
803/// - SYN: Invalid
804/// - RST: Delete connection
805/// - FIN: Closing
806/// - ACK: Established
807#[derive(Debug, Clone, PartialEq, Eq)]
808pub(crate) struct Established {
809    original: Peer,
810    reply: Peer,
811}
812state_from_state_struct!(Established);
813
814impl Established {
815    fn update(
816        self,
817        segment: &SegmentHeader,
818        payload_len: usize,
819        dir: ConnectionDirection,
820    ) -> (State, bool) {
821        let Self { original, reply } = self;
822
823        let (original, reply, fin_seen) = match do_established_update(
824            UpdatePeers { original, reply },
825            segment,
826            payload_len,
827            dir.clone(),
828        ) {
829            EstablishedUpdateResult::Success { new_original, new_reply, fin_seen } => {
830                (new_original, new_reply, fin_seen)
831            }
832            EstablishedUpdateResult::Invalid { original, reply } => {
833                return (Self { original, reply }.into(), false);
834            }
835            EstablishedUpdateResult::Reset => return (Closed {}.into(), true),
836        };
837
838        let new_state = if fin_seen {
839            Closing { original, reply }.into()
840        } else {
841            Established { original, reply }.into()
842        };
843
844        (new_state, true)
845    }
846}
847
848/// State for the Closing state.
849///
850/// State transitions for in-range segments regardless of direction:
851/// - SYN: Invalid
852/// - RST: Delete connection
853/// - FIN: Closing
854/// - ACK: Closing
855///
856/// The Closing state deletes the connection once FINs from both peers have been
857/// ACKed.
858#[derive(Debug, Clone, PartialEq, Eq)]
859pub(crate) struct Closing {
860    original: Peer,
861    reply: Peer,
862}
863state_from_state_struct!(Closing);
864
865impl Closing {
866    fn update(
867        self,
868        segment: &SegmentHeader,
869        payload_len: usize,
870        dir: ConnectionDirection,
871    ) -> (State, bool) {
872        let Self { original, reply } = self;
873
874        // NOTE: Segments after a FIN are somewhat invalid, but we do not
875        // attempt to handle them specially. Per RFC 9293 3.10.7.4:
876        //
877        //   Seventh, process the segment text. [After FIN,] this should not
878        //   occur since a FIN has been received from the remote side. Ignore
879        //   the segment text.
880        //
881        // Because these segments aren't completely invalid, handling them
882        // properly (and consistently with the endpoints) is difficult. It is
883        // not needed for correctness, since the connection will be torn down as
884        // soon as there's an ACK for both FINs anyway. This extra invalid data
885        // does not change that.
886        //
887        // Neither Linux nor gVisor do anything special for these segments.
888
889        let (original, reply) = match do_established_update(
890            UpdatePeers { original, reply },
891            segment,
892            payload_len,
893            dir.clone(),
894        ) {
895            EstablishedUpdateResult::Success { new_original, new_reply, fin_seen: _ } => {
896                (new_original, new_reply)
897            }
898            EstablishedUpdateResult::Invalid { original, reply } => {
899                return (Self { original, reply }.into(), false);
900            }
901            EstablishedUpdateResult::Reset => return (Closed {}.into(), true),
902        };
903
904        if original.fin_state.acked() && reply.fin_state.acked() {
905            // Removing the entry immediately is not expected to break any
906            // use-cases. The endpoints are ultimately responsible for
907            // respecting the TIME_WAIT state.
908            //
909            // The NAT entry will be removed as a consequence, but this is only
910            // a problem if a server wanted to reopen the connection with the
911            // client (but only during TIME_WAIT).
912            //
913            // TODO(https://fxbug.dev/355200767): Add TimeWait and reopening
914            // connections once simultaneous open is supported.
915            (Closed {}.into(), true)
916        } else {
917            (Closing { original, reply }.into(), true)
918        }
919    }
920}
921
922#[cfg(test)]
923mod tests {
924    use super::{
925        Closed, Closing, Established, EstablishedUpdateResult, FinState, Peer, State, SynSent,
926        Untracked, UpdatePeers, WaitingOnOpeningAck, do_established_update,
927    };
928
929    use assert_matches::assert_matches;
930    use netstack3_base::{
931        Control, HandshakeOptions, SegmentHeader, SeqNum, UnscaledWindowSize, WindowScale,
932        WindowSize,
933    };
934    use test_case::test_case;
935
936    use crate::conntrack::ConnectionDirection;
937
938    const ORIGINAL_ISS: SeqNum = SeqNum::new(0);
939    const REPLY_ISS: SeqNum = SeqNum::new(8192);
940    const ORIGINAL_WND: u16 = 16;
941    const REPLY_WND: u16 = 17;
942    const ORIGINAL_WS: u8 = 3;
943    const REPLY_WS: u8 = 4;
944    const ORIGINAL_PAYLOAD_LEN: usize = 12;
945    const REPLY_PAYLOAD_LEN: usize = 13;
946
947    impl Peer {
948        pub fn arbitrary() -> Peer {
949            Peer {
950                max_next_seq: SeqNum::new(0),
951                window_scale: WindowScale::new(0).unwrap(),
952                max_wnd_seq: SeqNum::new(0),
953                unacked_data: false,
954                max_wnd: WindowSize::new(0).unwrap(),
955                fin_state: FinState::NotSent,
956            }
957        }
958    }
959
960    #[test_case(None)]
961    #[test_case(Some(Control::FIN))]
962    #[test_case(Some(Control::RST))]
963    fn syn_sent_original_non_syn_segment(control: Option<Control>) {
964        let state = SynSent {
965            iss: ORIGINAL_ISS,
966            logical_len: 3,
967            advertised_window_scale: None,
968            window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
969        };
970
971        let segment = SegmentHeader {
972            seq: ORIGINAL_ISS,
973            wnd: UnscaledWindowSize::from(ORIGINAL_WND),
974            control,
975            ..Default::default()
976        };
977
978        let expected_state = state.clone().into();
979        assert_eq!(
980            state.update(&segment, ORIGINAL_PAYLOAD_LEN, ConnectionDirection::Original),
981            (expected_state, false)
982        );
983    }
984
985    #[test_case(SegmentHeader {
986        // Different from existing.
987        seq: ORIGINAL_ISS + 1,
988        wnd: UnscaledWindowSize::from(ORIGINAL_WND),
989        control: Some(Control::SYN),
990        options: HandshakeOptions {
991            // Same as existing.
992            window_scale: WindowScale::new(ORIGINAL_WS),
993            ..Default::default()
994        }.into(),
995        ..Default::default()
996    }; "different ISS")]
997    #[test_case(SegmentHeader {
998        // Same as existing.
999        seq: ORIGINAL_ISS,
1000        wnd: UnscaledWindowSize::from(ORIGINAL_WND),
1001        control: Some(Control::SYN),
1002        options: HandshakeOptions {
1003            // Different from existing.
1004            window_scale: WindowScale::new(ORIGINAL_WS + 1),
1005            ..Default::default()
1006        }.into(),
1007        ..Default::default()
1008    }; "different window scale")]
1009    #[test_case(SegmentHeader {
1010        seq: ORIGINAL_ISS,
1011        // ACK here is invalid.
1012        ack: Some(SeqNum::new(10)),
1013        wnd: UnscaledWindowSize::from(ORIGINAL_WND),
1014        control: Some(Control::SYN),
1015        options: HandshakeOptions {
1016            window_scale: WindowScale::new(2),
1017            ..Default::default()
1018        }.into(),
1019        ..Default::default()
1020    }; "ack not allowed")]
1021    fn syn_sent_original_syn_not_retransmit(segment: SegmentHeader) {
1022        let state = SynSent {
1023            iss: ORIGINAL_ISS,
1024            logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 1,
1025            advertised_window_scale: WindowScale::new(ORIGINAL_WS),
1026            window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1027        };
1028
1029        let expected_state = state.clone().into();
1030        assert_eq!(
1031            state.update(&segment, ORIGINAL_PAYLOAD_LEN, ConnectionDirection::Original),
1032            (expected_state, false)
1033        );
1034    }
1035
1036    #[test]
1037    fn syn_sent_original_syn_retransmit() {
1038        let state = SynSent {
1039            iss: ORIGINAL_ISS,
1040            logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 1,
1041            advertised_window_scale: WindowScale::new(ORIGINAL_WS),
1042            window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1043        };
1044
1045        let segment = SegmentHeader {
1046            seq: ORIGINAL_ISS,
1047            wnd: UnscaledWindowSize::from(ORIGINAL_WND + 10),
1048            control: Some(Control::SYN),
1049            options: HandshakeOptions {
1050                window_scale: WindowScale::new(ORIGINAL_WS),
1051                ..Default::default()
1052            }
1053            .into(),
1054            ..Default::default()
1055        };
1056
1057        let result = assert_matches!(
1058            state.update(
1059                &segment,
1060                ORIGINAL_PAYLOAD_LEN + 10,
1061                ConnectionDirection::Original
1062            ),
1063            (State::SynSent(s), true) => s
1064        );
1065
1066        assert_eq!(
1067            result,
1068            SynSent {
1069                iss: ORIGINAL_ISS,
1070                logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 10 + 1,
1071                advertised_window_scale: WindowScale::new(ORIGINAL_WS),
1072                window_size: WindowSize::from_u32(ORIGINAL_WND as u32 + 10).unwrap(),
1073            }
1074        )
1075    }
1076
1077    #[test_case(None)]
1078    #[test_case(Some(Control::FIN))]
1079    fn syn_sent_reply_non_syn_segment(control: Option<Control>) {
1080        let state = SynSent {
1081            iss: ORIGINAL_ISS,
1082            logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 1,
1083            advertised_window_scale: None,
1084            window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1085        };
1086
1087        let segment = SegmentHeader {
1088            seq: ORIGINAL_ISS,
1089            wnd: UnscaledWindowSize::from(ORIGINAL_WND),
1090            control,
1091            ..Default::default()
1092        };
1093
1094        let expected_state = state.clone().into();
1095        assert_eq!(
1096            state.update(&segment, REPLY_PAYLOAD_LEN, ConnectionDirection::Reply),
1097            (expected_state, false)
1098        );
1099    }
1100
1101    #[test_case(ORIGINAL_ISS, None; "small invalid")]
1102    #[test_case(
1103        ORIGINAL_ISS + 1, Some(Closed {}.into());
1104        "smallest valid"
1105    )]
1106    #[test_case(
1107        ORIGINAL_ISS + ORIGINAL_PAYLOAD_LEN as u32 + 1,
1108        Some(Closed {}.into());
1109        "largest valid"
1110    )]
1111    #[test_case(
1112        ORIGINAL_ISS + ORIGINAL_PAYLOAD_LEN as u32 + 2,
1113        None;
1114        "large invalid"
1115    )]
1116    fn syn_sent_reply_rst_segment(ack: SeqNum, new_state: Option<State>) {
1117        let state = SynSent {
1118            iss: ORIGINAL_ISS,
1119            logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 1,
1120            advertised_window_scale: None,
1121            window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1122        };
1123
1124        let segment = SegmentHeader {
1125            seq: ORIGINAL_ISS,
1126            ack: Some(ack),
1127            wnd: UnscaledWindowSize::from(ORIGINAL_WND),
1128            control: Some(Control::RST),
1129            ..Default::default()
1130        };
1131
1132        let (expected_state, valid) = match new_state {
1133            Some(state) => (state, true),
1134            None => (state.clone().into(), false),
1135        };
1136
1137        assert_eq!(
1138            state.update(&segment, /*payload_len*/ 0, ConnectionDirection::Reply),
1139            (expected_state, valid)
1140        );
1141    }
1142
1143    #[test]
1144    fn syn_sent_reply_simultaneous_open() {
1145        let state = SynSent {
1146            iss: ORIGINAL_ISS,
1147            logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 1,
1148            advertised_window_scale: WindowScale::new(ORIGINAL_WS),
1149            window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1150        };
1151
1152        let segment = SegmentHeader {
1153            seq: ORIGINAL_ISS,
1154            wnd: UnscaledWindowSize::from(ORIGINAL_WND + 10),
1155            control: Some(Control::SYN),
1156            ..Default::default()
1157        };
1158
1159        assert_eq!(
1160            state.update(&segment, /*payload_len*/ 0, ConnectionDirection::Reply),
1161            (Untracked {}.into(), true)
1162        );
1163    }
1164
1165    #[test_case(ORIGINAL_ISS; "too low")]
1166    #[test_case(ORIGINAL_ISS + ORIGINAL_PAYLOAD_LEN + 2; "too high")]
1167    fn syn_sent_reply_syn_ack_not_in_range(ack: SeqNum) {
1168        let state = SynSent {
1169            iss: ORIGINAL_ISS,
1170            logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 1,
1171            advertised_window_scale: None,
1172            window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1173        };
1174
1175        let segment = SegmentHeader {
1176            seq: REPLY_ISS,
1177            ack: Some(ack),
1178            wnd: UnscaledWindowSize::from(REPLY_WND),
1179            control: Some(Control::SYN),
1180            ..Default::default()
1181        };
1182
1183        let expected_state = state.clone().into();
1184        assert_eq!(
1185            state.update(&segment, REPLY_PAYLOAD_LEN, ConnectionDirection::Reply),
1186            (expected_state, false)
1187        );
1188    }
1189
1190    #[test_case(None)]
1191    #[test_case(Some(WindowScale::new(REPLY_WS).unwrap()))]
1192    fn syn_sent_reply_syn_ack(reply_window_scale: Option<WindowScale>) {
1193        let state = SynSent {
1194            iss: ORIGINAL_ISS,
1195            logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 1,
1196            advertised_window_scale: WindowScale::new(ORIGINAL_WS),
1197            window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1198        };
1199
1200        let segment = SegmentHeader {
1201            seq: REPLY_ISS,
1202            ack: Some(ORIGINAL_ISS + 1),
1203            wnd: UnscaledWindowSize::from(REPLY_WND),
1204            control: Some(Control::SYN),
1205            options: HandshakeOptions { window_scale: reply_window_scale, ..Default::default() }
1206                .into(),
1207            ..Default::default()
1208        };
1209
1210        let new_state = assert_matches!(
1211            state.update(
1212                &segment,
1213                REPLY_PAYLOAD_LEN,
1214                ConnectionDirection::Reply
1215            ),
1216            (State::WaitingOnOpeningAck(s), true) => s
1217        );
1218
1219        let (original_window_scale, reply_window_scale) = match reply_window_scale {
1220            Some(s) => (WindowScale::new(ORIGINAL_WS).unwrap(), s),
1221            None => (WindowScale::ZERO, WindowScale::ZERO),
1222        };
1223
1224        assert_eq!(
1225            new_state,
1226            WaitingOnOpeningAck {
1227                original: Peer {
1228                    window_scale: original_window_scale,
1229                    max_wnd: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1230                    max_wnd_seq: REPLY_ISS + ORIGINAL_WND as u32,
1231                    max_next_seq: ORIGINAL_ISS + ORIGINAL_PAYLOAD_LEN + 1,
1232                    unacked_data: true,
1233                    fin_state: FinState::NotSent,
1234                },
1235                reply: Peer {
1236                    window_scale: reply_window_scale,
1237                    max_wnd: WindowSize::from_u32(REPLY_WND as u32).unwrap(),
1238                    max_wnd_seq: ORIGINAL_ISS + 1 + REPLY_WND as u32,
1239                    max_next_seq: REPLY_ISS + REPLY_PAYLOAD_LEN + 1,
1240                    unacked_data: true,
1241                    fin_state: FinState::NotSent,
1242                }
1243            }
1244        );
1245    }
1246
1247    #[test_case(FinState::NotSent, SeqNum::new(9) => FinState::Sent(SeqNum::new(9)))]
1248    #[test_case(FinState::Sent(SeqNum::new(9)), SeqNum::new(8) => FinState::Sent(SeqNum::new(8)))]
1249    #[test_case(FinState::Sent(SeqNum::new(9)), SeqNum::new(9) => FinState::Sent(SeqNum::new(9)))]
1250    #[test_case(FinState::Sent(SeqNum::new(9)), SeqNum::new(10) => FinState::Sent(SeqNum::new(9)))]
1251    #[test_case(FinState::Acked, SeqNum::new(9) => FinState::Acked)]
1252    fn fin_state_update_fin_sent(fin_state: FinState, seq: SeqNum) -> FinState {
1253        fin_state.update_fin_sent(seq)
1254    }
1255
1256    #[test_case(FinState::NotSent, SeqNum::new(10) => FinState::NotSent)]
1257    #[test_case(FinState::Sent(SeqNum::new(9)), SeqNum::new(9) => FinState::Sent(SeqNum::new(9)))]
1258    #[test_case(FinState::Sent(SeqNum::new(9)), SeqNum::new(10) => FinState::Acked)]
1259    #[test_case(FinState::Acked, SeqNum::new(10) => FinState::Acked)]
1260    fn fin_state_update_ack_received(fin_state: FinState, ack: SeqNum) -> FinState {
1261        fin_state.update_ack_received(ack)
1262    }
1263
1264    const RECV_MAX_NEXT_SEQ: SeqNum = SeqNum::new(66_001);
1265    const RECV_MAX_WND_SEQ: SeqNum = SeqNum::new(1424);
1266
1267    #[test_case(SeqNum::new(424), 200, SeqNum::new(1) => true; "success low seq/ack")]
1268    #[test_case(RECV_MAX_WND_SEQ, 0, RECV_MAX_NEXT_SEQ => true; "success high seq/ack")]
1269    #[test_case(RECV_MAX_WND_SEQ + 1, 0, SeqNum::new(1) => false; "bad equation I")]
1270    #[test_case(SeqNum::new(424), 199, SeqNum::new(1) => false; "bad equation II")]
1271    #[test_case(SeqNum::new(424), 200, RECV_MAX_NEXT_SEQ + 1 => false; "bad equation III")]
1272    #[test_case(SeqNum::new(424), 200, SeqNum::new(0) => false; "bad equation IV")]
1273    fn ack_segment_valid_test(seq: SeqNum, len: u32, ack: SeqNum) -> bool {
1274        let sender = Peer { max_next_seq: SeqNum::new(1024), ..Peer::arbitrary() };
1275
1276        // MAXACKWINDOW is going to be 66000 due to window shift of 0.
1277        let receiver = Peer {
1278            window_scale: WindowScale::new(0).unwrap(),
1279            max_wnd: WindowSize::new(400).unwrap(),
1280            max_next_seq: RECV_MAX_NEXT_SEQ,
1281            max_wnd_seq: RECV_MAX_WND_SEQ,
1282            ..Peer::arbitrary()
1283        };
1284
1285        Peer::ack_segment_valid(&sender, &receiver, seq, len, ack)
1286    }
1287
1288    struct PeerUpdateSenderArgs {
1289        seq: SeqNum,
1290        len: u32,
1291        ack: SeqNum,
1292        wnd: UnscaledWindowSize,
1293        fin_seen: bool,
1294    }
1295
1296    #[test_case(
1297        Peer {
1298            window_scale: WindowScale::new(3).unwrap(),
1299            max_wnd: WindowSize::new(16).unwrap(),
1300            max_wnd_seq: SeqNum::new(127),
1301            max_next_seq: SeqNum::new(1024),
1302            unacked_data: false,
1303            fin_state: FinState::NotSent,
1304        },
1305        PeerUpdateSenderArgs {
1306            seq: SeqNum::new(1025),
1307            len: 10,
1308            ack: SeqNum::new(100),
1309            wnd: UnscaledWindowSize::from_u32(4),
1310            fin_seen: false
1311        } => Peer {
1312            window_scale: WindowScale::new(3).unwrap(),
1313            max_wnd: WindowSize::new(32).unwrap(),
1314            max_wnd_seq: SeqNum::new(132),
1315            max_next_seq: SeqNum::new(1035),
1316            unacked_data: true,
1317            fin_state: FinState::NotSent,
1318        }; "packet larger"
1319    )]
1320    #[test_case(
1321        Peer {
1322            window_scale: WindowScale::new(3).unwrap(),
1323            max_wnd: WindowSize::new(16).unwrap(),
1324            max_wnd_seq: SeqNum::new(127),
1325            max_next_seq: SeqNum::new(1024),
1326            unacked_data: false,
1327            fin_state: FinState::NotSent,
1328        },
1329        PeerUpdateSenderArgs {
1330            seq: SeqNum::new(1000),
1331            len: 10,
1332            ack: SeqNum::new(0),
1333            wnd: UnscaledWindowSize::from_u32(0),
1334            fin_seen: false
1335        } => Peer {
1336            window_scale: WindowScale::new(3).unwrap(),
1337            max_wnd: WindowSize::new(16).unwrap(),
1338            max_wnd_seq: SeqNum::new(127),
1339            max_next_seq: SeqNum::new(1024),
1340            unacked_data: false,
1341            fin_state: FinState::NotSent,
1342        }; "packet smaller"
1343    )]
1344    #[test_case(
1345        Peer {
1346            window_scale: WindowScale::new(3).unwrap(),
1347            max_wnd: WindowSize::new(16).unwrap(),
1348            max_wnd_seq: SeqNum::new(127),
1349            max_next_seq: SeqNum::new(1024),
1350            unacked_data: false,
1351            fin_state: FinState::NotSent,
1352        },
1353        PeerUpdateSenderArgs {
1354            seq: SeqNum::new(1000),
1355            len: 10,
1356            ack: SeqNum::new(0),
1357            wnd: UnscaledWindowSize::from_u32(0),
1358            fin_seen: true
1359        } => Peer {
1360            window_scale: WindowScale::new(3).unwrap(),
1361            max_wnd: WindowSize::new(16).unwrap(),
1362            max_wnd_seq: SeqNum::new(127),
1363            max_next_seq: SeqNum::new(1024),
1364            unacked_data: false,
1365            fin_state: FinState::Sent(SeqNum::new(1000 + 9)),
1366        }; "fin sent"
1367    )]
1368    fn peer_update_sender_test(peer: Peer, args: PeerUpdateSenderArgs) -> Peer {
1369        peer.update_sender(args.seq, args.len, args.ack, args.wnd, args.fin_seen)
1370    }
1371
1372    #[test_case(
1373        Peer { max_next_seq: SeqNum::new(1024), ..Peer::arbitrary() },
1374        SeqNum::new(1024) => Peer { max_next_seq: SeqNum::new(1024), ..Peer::arbitrary() };
1375        "unset unacked data"
1376    )]
1377    #[test_case(
1378        Peer { max_next_seq: SeqNum::new(1024), ..Peer::arbitrary() },
1379        SeqNum::new(1023) => Peer { max_next_seq: SeqNum::new(1024), ..Peer::arbitrary() };
1380        "don't unset unacked data"
1381    )]
1382    #[test_case(
1383        Peer { fin_state: FinState::Sent(SeqNum::new(9)), ..Peer::arbitrary() },
1384        SeqNum::new(10) => Peer { fin_state: FinState::Acked, ..Peer::arbitrary() };
1385        "update fin state"
1386    )]
1387    fn peer_update_receiver_test(peer: Peer, ack: SeqNum) -> Peer {
1388        peer.update_receiver(ack)
1389    }
1390
1391    // This is mostly to ensure that we don't accidentally overflow a u32, since
1392    // it's such a basic calculation.
1393    #[test]
1394    fn peer_max_ack_window() {
1395        let max_peer = Peer { window_scale: WindowScale::MAX, ..Peer::arbitrary() };
1396        let min_peer = Peer { window_scale: WindowScale::new(0).unwrap(), ..Peer::arbitrary() };
1397
1398        assert_eq!(max_peer.max_ack_window(), 1_081_344_000u32);
1399        assert_eq!(min_peer.max_ack_window(), 66_000u32);
1400    }
1401
1402    enum EstablishedUpdateTestResult {
1403        Success { new_original: Peer, new_reply: Peer, fin_seen: bool },
1404        Invalid,
1405        Reset,
1406    }
1407
1408    struct EstablishedUpdateTestArgs {
1409        segment: SegmentHeader,
1410        payload_len: usize,
1411        dir: ConnectionDirection,
1412        expected: EstablishedUpdateTestResult,
1413    }
1414
1415    #[test_case(
1416        EstablishedUpdateTestArgs {
1417            segment: SegmentHeader {
1418                seq: SeqNum::new(1400),
1419                ack: Some(SeqNum::new(66_001)),
1420                wnd: UnscaledWindowSize::from(10),
1421                ..Default::default()
1422            },
1423            payload_len: 24,
1424            dir: ConnectionDirection::Original,
1425            expected: EstablishedUpdateTestResult::Success {
1426                new_original: Peer {
1427                    window_scale: WindowScale::new(2).unwrap(),
1428                    // Changed.
1429                    max_wnd: WindowSize::new(40).unwrap(),
1430                    max_wnd_seq: SeqNum::new(70_000),
1431                    // Changed.
1432                    max_next_seq: SeqNum::new(1424),
1433                    // Changed.
1434                    unacked_data: true,
1435                    fin_state: FinState::NotSent,
1436                },
1437                new_reply: Peer {
1438                    window_scale: WindowScale::new(0).unwrap(),
1439                    max_wnd: WindowSize::new(400).unwrap(),
1440                    max_wnd_seq: SeqNum::new(1424),
1441                    max_next_seq: SeqNum::new(66_001),
1442                    // Changed.
1443                    unacked_data: false,
1444                    fin_state: FinState::NotSent,
1445                },
1446                fin_seen: false,
1447            }
1448        }; "success original"
1449    )]
1450    #[test_case(
1451        EstablishedUpdateTestArgs {
1452            segment: SegmentHeader {
1453                seq: SeqNum::new(66_100),
1454                ack: Some(SeqNum::new(1024)),
1455                wnd: UnscaledWindowSize::from(10),
1456                control: Some(Control::FIN),
1457                ..Default::default()
1458            },
1459            payload_len: 0,
1460            dir: ConnectionDirection::Reply,
1461            expected: EstablishedUpdateTestResult::Success {
1462              // No changes in new_original.
1463              new_original: Peer {
1464                  window_scale: WindowScale::new(2).unwrap(),
1465                  max_wnd: WindowSize::new(0).unwrap(),
1466                  max_wnd_seq: SeqNum::new(70_000),
1467                  max_next_seq: SeqNum::new(1024),
1468                  unacked_data: false,
1469                  fin_state: FinState::NotSent,
1470              },
1471              new_reply: Peer {
1472                  window_scale: WindowScale::new(0).unwrap(),
1473                  max_wnd: WindowSize::new(400).unwrap(),
1474                  max_wnd_seq: SeqNum::new(1424),
1475                  max_next_seq: SeqNum::new(66_101),
1476                  unacked_data: true,
1477                  fin_state: FinState::Sent(SeqNum::new(66_100)),
1478              },
1479              fin_seen: true,
1480            }
1481        }; "success reply"
1482    )]
1483    #[test_case(
1484        EstablishedUpdateTestArgs {
1485            segment: SegmentHeader {
1486                seq: SeqNum::new(1400),
1487                ack: Some(SeqNum::new(66_001)),
1488                wnd: UnscaledWindowSize::from(10),
1489                control: Some(Control::RST),
1490                ..Default::default()
1491            },
1492            payload_len: 24,
1493            dir: ConnectionDirection::Original,
1494            expected: EstablishedUpdateTestResult::Reset,
1495        }; "RST"
1496    )]
1497    #[test_case(
1498        EstablishedUpdateTestArgs {
1499            segment: SegmentHeader {
1500                seq: SeqNum::new(1400),
1501                wnd: UnscaledWindowSize::from(10),
1502                ..Default::default()
1503            },
1504            // These don't matter for the test
1505            payload_len: 24,
1506            dir: ConnectionDirection::Original,
1507            expected: EstablishedUpdateTestResult::Invalid,
1508        }; "missing ack"
1509    )]
1510    #[test_case(
1511        EstablishedUpdateTestArgs {
1512            segment: SegmentHeader {
1513                // Too low. Doesn't meet equation II.
1514                seq: SeqNum::new(0),
1515                wnd: UnscaledWindowSize::from(10),
1516                ..Default::default()
1517            },
1518            // These don't matter for the test
1519            payload_len: 24,
1520            dir: ConnectionDirection::Original,
1521            expected: EstablishedUpdateTestResult::Invalid,
1522        }; "invalid equation bounds"
1523    )]
1524    #[test_case(
1525        EstablishedUpdateTestArgs {
1526            segment: SegmentHeader {
1527                seq: SeqNum::new(1400),
1528                ack: Some(SeqNum::new(66_001)),
1529                wnd: UnscaledWindowSize::from(10),
1530                control: Some(Control::SYN),
1531                ..Default::default()
1532            },
1533            payload_len: 24,
1534            dir: ConnectionDirection::Original,
1535            expected: EstablishedUpdateTestResult::Invalid,
1536        }; "SYN not allowed"
1537    )]
1538    fn do_established_update_test(args: EstablishedUpdateTestArgs) {
1539        let original = Peer {
1540            window_scale: WindowScale::new(2).unwrap(),
1541            max_wnd: WindowSize::new(0).unwrap(),
1542            max_wnd_seq: SeqNum::new(70_000),
1543            max_next_seq: SeqNum::new(1024),
1544            unacked_data: false,
1545            fin_state: FinState::NotSent,
1546        };
1547
1548        let reply = Peer {
1549            window_scale: WindowScale::new(0).unwrap(),
1550            max_wnd: WindowSize::new(400).unwrap(),
1551            max_wnd_seq: SeqNum::new(1424),
1552            max_next_seq: SeqNum::new(66_001),
1553            unacked_data: true,
1554            fin_state: FinState::NotSent,
1555        };
1556
1557        let expected_result = match args.expected {
1558            EstablishedUpdateTestResult::Success { new_original, new_reply, fin_seen } => {
1559                EstablishedUpdateResult::Success { new_original, new_reply, fin_seen }
1560            }
1561            EstablishedUpdateTestResult::Invalid => EstablishedUpdateResult::Invalid {
1562                original: original.clone(),
1563                reply: reply.clone(),
1564            },
1565            EstablishedUpdateTestResult::Reset => EstablishedUpdateResult::Reset,
1566        };
1567
1568        assert_eq!(
1569            do_established_update(
1570                UpdatePeers { original: original, reply: reply },
1571                &args.segment,
1572                args.payload_len,
1573                args.dir,
1574            ),
1575            expected_result
1576        );
1577    }
1578
1579    struct StateUpdateTestArgs {
1580        segment: SegmentHeader,
1581        payload_len: usize,
1582        dir: ConnectionDirection,
1583        expected: Option<State>,
1584    }
1585
1586    #[test_case(
1587        StateUpdateTestArgs {
1588            segment: SegmentHeader {
1589                seq: SeqNum::new(1400),
1590                ack: Some(SeqNum::new(66_001)),
1591                wnd: UnscaledWindowSize::from(10),
1592                ..Default::default()
1593            },
1594            payload_len: 24,
1595            dir: ConnectionDirection::Original,
1596            expected: Some(Established {
1597                original: Peer {
1598                    window_scale: WindowScale::new(2).unwrap(),
1599                    max_wnd: WindowSize::new(40).unwrap(),
1600                    max_wnd_seq: SeqNum::new(70_000),
1601                    max_next_seq: SeqNum::new(1424),
1602                    unacked_data: true,
1603                    fin_state: FinState::NotSent,
1604                },
1605                reply: Peer {
1606                    window_scale: WindowScale::new(0).unwrap(),
1607                    max_wnd: WindowSize::new(400).unwrap(),
1608                    max_wnd_seq: SeqNum::new(1424),
1609                    max_next_seq: SeqNum::new(66_001),
1610                    unacked_data: false,
1611                    fin_state: FinState::NotSent,
1612                },
1613            }.into()),
1614        }; "established"
1615    )]
1616    #[test_case(
1617        StateUpdateTestArgs {
1618            segment: SegmentHeader {
1619                seq: SeqNum::new(66_100),
1620                ack: Some(SeqNum::new(1024)),
1621                wnd: UnscaledWindowSize::from(10),
1622                control: Some(Control::FIN),
1623                ..Default::default()
1624            },
1625            payload_len: 0,
1626            dir: ConnectionDirection::Reply,
1627            expected: Some(Closing {
1628                original: Peer {
1629                    window_scale: WindowScale::new(2).unwrap(),
1630                    max_wnd: WindowSize::new(0).unwrap(),
1631                    max_wnd_seq: SeqNum::new(70_000),
1632                    max_next_seq: SeqNum::new(1024),
1633                    unacked_data: false,
1634                    fin_state: FinState::NotSent,
1635                },
1636                reply: Peer {
1637                    window_scale: WindowScale::new(0).unwrap(),
1638                    max_wnd: WindowSize::new(400).unwrap(),
1639                    max_wnd_seq: SeqNum::new(1424),
1640                    max_next_seq: SeqNum::new(66_101),
1641                    unacked_data: true,
1642                    fin_state: FinState::Sent(SeqNum::new(66_100)),
1643                },
1644            }.into()),
1645        }; "closing"
1646    )]
1647    #[test_case(
1648        StateUpdateTestArgs {
1649            segment: SegmentHeader {
1650                seq: SeqNum::new(66_100),
1651                ack: Some(SeqNum::new(1024)),
1652                wnd: UnscaledWindowSize::from(10),
1653                ..Default::default()
1654            },
1655            payload_len: 0,
1656            dir: ConnectionDirection::Reply,
1657            expected: Some(WaitingOnOpeningAck {
1658                original: Peer {
1659                    window_scale: WindowScale::new(2).unwrap(),
1660                    max_wnd: WindowSize::new(0).unwrap(),
1661                    max_wnd_seq: SeqNum::new(70_000),
1662                    max_next_seq: SeqNum::new(1024),
1663                    unacked_data: false,
1664                    fin_state: FinState::NotSent,
1665                },
1666                reply: Peer {
1667                    window_scale: WindowScale::new(0).unwrap(),
1668                    max_wnd: WindowSize::new(400).unwrap(),
1669                    max_wnd_seq: SeqNum::new(1424),
1670                    max_next_seq: SeqNum::new(66_100),
1671                    unacked_data: true,
1672                    fin_state: FinState::NotSent,
1673                },
1674            }.into())
1675        }; "update in place"
1676    )]
1677    #[test_case(
1678        StateUpdateTestArgs {
1679            segment: SegmentHeader {
1680                // Fails equation I.
1681                seq: SeqNum::new(100_000),
1682                ack: Some(SeqNum::new(1024)),
1683                wnd: UnscaledWindowSize::from(10),
1684                ..Default::default()
1685            },
1686            payload_len: 0,
1687            dir: ConnectionDirection::Reply,
1688            expected: None
1689        }; "invalid"
1690    )]
1691    #[test_case(
1692        StateUpdateTestArgs {
1693            segment: SegmentHeader {
1694                seq: SeqNum::new(1400),
1695                ack: Some(SeqNum::new(66_001)),
1696                wnd: UnscaledWindowSize::from(10),
1697                control: Some(Control::RST),
1698                ..Default::default()
1699            },
1700            payload_len: 24,
1701            dir: ConnectionDirection::Original,
1702            expected: Some(Closed {}.into()),
1703        }; "rst"
1704    )]
1705    fn waiting_on_opening_ack_test(args: StateUpdateTestArgs) {
1706        let state = WaitingOnOpeningAck {
1707            original: Peer {
1708                window_scale: WindowScale::new(2).unwrap(),
1709                max_wnd: WindowSize::new(0).unwrap(),
1710                max_wnd_seq: SeqNum::new(70_000),
1711                max_next_seq: SeqNum::new(1024),
1712                unacked_data: false,
1713                fin_state: FinState::NotSent,
1714            },
1715            reply: Peer {
1716                window_scale: WindowScale::new(0).unwrap(),
1717                max_wnd: WindowSize::new(400).unwrap(),
1718                max_wnd_seq: SeqNum::new(1424),
1719                max_next_seq: SeqNum::new(66_001),
1720                unacked_data: true,
1721                fin_state: FinState::NotSent,
1722            },
1723        };
1724
1725        let (new_state, valid) = match args.expected {
1726            Some(new_state) => (new_state, true),
1727            None => (state.clone().into(), false),
1728        };
1729
1730        assert_eq!(state.update(&args.segment, args.payload_len, args.dir), (new_state, valid));
1731    }
1732
1733    #[test_case(
1734        StateUpdateTestArgs {
1735            segment: SegmentHeader {
1736                seq: SeqNum::new(1400),
1737                ack: Some(SeqNum::new(66_001)),
1738                wnd: UnscaledWindowSize::from(10),
1739                ..Default::default()
1740            },
1741            payload_len: 24,
1742            dir: ConnectionDirection::Original,
1743            expected: Some(Established {
1744                original: Peer {
1745                    window_scale: WindowScale::new(2).unwrap(),
1746                    max_wnd: WindowSize::new(40).unwrap(),
1747                    max_wnd_seq: SeqNum::new(70_000),
1748                    max_next_seq: SeqNum::new(1424),
1749                    // This is becoming true because `segment.seq > original.max_next_seq`.
1750                    unacked_data: true,
1751                    fin_state: FinState::NotSent,
1752                },
1753                reply: Peer {
1754                    window_scale: WindowScale::new(0).unwrap(),
1755                    max_wnd: WindowSize::new(400).unwrap(),
1756                    max_wnd_seq: SeqNum::new(1424),
1757                    max_next_seq: SeqNum::new(66_001),
1758                    // This is becoming true because `segment.ack == reply.max_next_seq`.
1759                    unacked_data: false,
1760                    fin_state: FinState::NotSent,
1761                },
1762            }.into()),
1763        }; "update original"
1764    )]
1765    #[test_case(
1766        StateUpdateTestArgs {
1767            segment: SegmentHeader {
1768                seq: SeqNum::new(66_100),
1769                ack: Some(SeqNum::new(1024)),
1770                wnd: UnscaledWindowSize::from(10),
1771                control: Some(Control::FIN),
1772                ..Default::default()
1773            },
1774            payload_len: 0,
1775            dir: ConnectionDirection::Reply,
1776            expected: Some(Closing {
1777                original: Peer {
1778                    window_scale: WindowScale::new(2).unwrap(),
1779                    max_wnd: WindowSize::new(0).unwrap(),
1780                    max_wnd_seq: SeqNum::new(70_000),
1781                    max_next_seq: SeqNum::new(1024),
1782                    unacked_data: false,
1783                    fin_state: FinState::NotSent,
1784                },
1785                reply: Peer {
1786                    window_scale: WindowScale::new(0).unwrap(),
1787                    max_wnd: WindowSize::new(400).unwrap(),
1788                    max_wnd_seq: SeqNum::new(1424),
1789                    max_next_seq: SeqNum::new(66_101),
1790                    unacked_data: true,
1791                    fin_state: FinState::Sent(SeqNum::new(66_100)),
1792                },
1793            }.into()),
1794        }; "closing"
1795    )]
1796    #[test_case(
1797        StateUpdateTestArgs {
1798            segment: SegmentHeader {
1799                seq: SeqNum::new(1400),
1800                // Fails equation III.
1801                ack: Some(SeqNum::new(100_000)),
1802                wnd: UnscaledWindowSize::from(10),
1803                ..Default::default()
1804            },
1805            payload_len: 24,
1806            dir: ConnectionDirection::Original,
1807            expected: None,
1808        }; "invalid"
1809    )]
1810    #[test_case(
1811        StateUpdateTestArgs {
1812            segment: SegmentHeader {
1813                seq: SeqNum::new(1400),
1814                ack: Some(SeqNum::new(66_001)),
1815                wnd: UnscaledWindowSize::from(10),
1816                control: Some(Control::RST),
1817                ..Default::default()
1818            },
1819            payload_len: 24,
1820            dir: ConnectionDirection::Original,
1821            expected: Some(Closed {}.into()),
1822        }; "rst"
1823    )]
1824    fn established_test(args: StateUpdateTestArgs) {
1825        let state = Established {
1826            original: Peer {
1827                window_scale: WindowScale::new(2).unwrap(),
1828                max_wnd: WindowSize::new(0).unwrap(),
1829                max_wnd_seq: SeqNum::new(70_000),
1830                max_next_seq: SeqNum::new(1024),
1831                unacked_data: false,
1832                fin_state: FinState::NotSent,
1833            },
1834            reply: Peer {
1835                window_scale: WindowScale::new(0).unwrap(),
1836                max_wnd: WindowSize::new(400).unwrap(),
1837                max_wnd_seq: SeqNum::new(1424),
1838                max_next_seq: SeqNum::new(66_001),
1839                unacked_data: true,
1840                fin_state: FinState::NotSent,
1841            },
1842        };
1843
1844        let (new_state, valid) = match args.expected {
1845            Some(new_state) => (new_state, true),
1846            None => (state.clone().into(), false),
1847        };
1848
1849        assert_eq!(state.update(&args.segment, args.payload_len, args.dir), (new_state, valid));
1850    }
1851
1852    #[test_case(
1853        StateUpdateTestArgs {
1854            segment: SegmentHeader {
1855                seq: SeqNum::new(1400),
1856                ack: Some(SeqNum::new(66_001)),
1857                wnd: UnscaledWindowSize::from(10),
1858                ..Default::default()
1859            },
1860            payload_len: 24,
1861            dir: ConnectionDirection::Original,
1862            expected: Some(Closing {
1863                original: Peer {
1864                    window_scale: WindowScale::new(2).unwrap(),
1865                    max_wnd: WindowSize::new(40).unwrap(),
1866                    max_wnd_seq: SeqNum::new(70_000),
1867                    max_next_seq: SeqNum::new(1424),
1868                    unacked_data: true,
1869                    fin_state: FinState::NotSent,
1870                },
1871                reply: Peer {
1872                    window_scale: WindowScale::new(0).unwrap(),
1873                    max_wnd: WindowSize::new(400).unwrap(),
1874                    max_wnd_seq: SeqNum::new(1424),
1875                    max_next_seq: SeqNum::new(66_001),
1876                    unacked_data: false,
1877                    fin_state: FinState::Acked,
1878                },
1879            }.into()),
1880        }; "update original"
1881    )]
1882    #[test_case(
1883        StateUpdateTestArgs {
1884            segment: SegmentHeader {
1885                seq: SeqNum::new(1400),
1886                // Fails equation III.
1887                ack: Some(SeqNum::new(100_000)),
1888                wnd: UnscaledWindowSize::from(10),
1889                ..Default::default()
1890            },
1891            payload_len: 24,
1892            dir: ConnectionDirection::Original,
1893            expected: None,
1894        }; "invalid"
1895    )]
1896    #[test_case(
1897        StateUpdateTestArgs {
1898            segment: SegmentHeader {
1899                seq: SeqNum::new(1400),
1900                ack: Some(SeqNum::new(66_001)),
1901                wnd: UnscaledWindowSize::from(10),
1902                control: Some(Control::RST),
1903                ..Default::default()
1904            },
1905            payload_len: 0,
1906            dir: ConnectionDirection::Original,
1907            expected: Some (Closed {}.into())
1908        }; "rst"
1909    )]
1910    fn closing_test(args: StateUpdateTestArgs) {
1911        let state = Closing {
1912            original: Peer {
1913                window_scale: WindowScale::new(2).unwrap(),
1914                max_wnd: WindowSize::new(0).unwrap(),
1915                max_wnd_seq: SeqNum::new(70_000),
1916                max_next_seq: SeqNum::new(1024),
1917                unacked_data: true,
1918                fin_state: FinState::NotSent,
1919            },
1920            reply: Peer {
1921                window_scale: WindowScale::new(0).unwrap(),
1922                max_wnd: WindowSize::new(400).unwrap(),
1923                max_wnd_seq: SeqNum::new(1424),
1924                max_next_seq: SeqNum::new(66_001),
1925                unacked_data: false,
1926                fin_state: FinState::Acked,
1927            },
1928        };
1929
1930        let (new_state, valid) = match args.expected {
1931            Some(new_state) => (new_state, true),
1932            None => (state.clone().into(), false),
1933        };
1934
1935        assert_eq!(state.update(&args.segment, args.payload_len, args.dir), (new_state, valid));
1936    }
1937
1938    #[test]
1939    fn closing_complete_test() {
1940        let state = Closing {
1941            original: Peer {
1942                window_scale: WindowScale::new(2).unwrap(),
1943                max_wnd: WindowSize::new(0).unwrap(),
1944                max_wnd_seq: SeqNum::new(70_000),
1945                max_next_seq: SeqNum::new(1024),
1946                unacked_data: true,
1947                fin_state: FinState::Sent(SeqNum::new(1023)),
1948            },
1949            reply: Peer {
1950                window_scale: WindowScale::new(0).unwrap(),
1951                max_wnd: WindowSize::new(400).unwrap(),
1952                max_wnd_seq: SeqNum::new(1424),
1953                max_next_seq: SeqNum::new(66_001),
1954                unacked_data: false,
1955                fin_state: FinState::Acked,
1956            },
1957        };
1958
1959        let segment = SegmentHeader {
1960            seq: SeqNum::new(66_100),
1961            ack: Some(SeqNum::new(1024)),
1962            wnd: UnscaledWindowSize::from(10),
1963            ..Default::default()
1964        };
1965
1966        assert_matches!(
1967            state.update(&segment, /* payload_len */ 0, ConnectionDirection::Reply),
1968            (State::Closed(_), true)
1969        );
1970    }
1971}