Skip to main content

smoltcp/wire/
tcp.rs

1use byteorder::{ByteOrder, NetworkEndian};
2use core::{cmp, fmt, ops};
3
4use super::{Error, Result};
5use crate::phy::ChecksumCapabilities;
6use crate::wire::ip::checksum;
7use crate::wire::{IpAddress, IpProtocol};
8
9/// A TCP sequence number.
10///
11/// A sequence number is a monotonically advancing integer modulo 2<sup>32</sup>.
12/// Sequence numbers do not have a discontiguity when compared pairwise across a signed overflow.
13#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
14pub struct SeqNumber(pub i32);
15
16impl SeqNumber {
17    pub fn max(self, rhs: Self) -> Self {
18        if self > rhs { self } else { rhs }
19    }
20
21    pub fn min(self, rhs: Self) -> Self {
22        if self < rhs { self } else { rhs }
23    }
24}
25
26impl fmt::Display for SeqNumber {
27    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28        write!(f, "{}", self.0 as u32)
29    }
30}
31
32#[cfg(feature = "defmt")]
33impl defmt::Format for SeqNumber {
34    fn format(&self, fmt: defmt::Formatter) {
35        defmt::write!(fmt, "{}", self.0 as u32);
36    }
37}
38
39impl ops::Add<usize> for SeqNumber {
40    type Output = SeqNumber;
41
42    fn add(self, rhs: usize) -> SeqNumber {
43        if rhs > i32::MAX as usize {
44            panic!("attempt to add to sequence number with unsigned overflow")
45        }
46        SeqNumber(self.0.wrapping_add(rhs as i32))
47    }
48}
49
50impl ops::Sub<usize> for SeqNumber {
51    type Output = SeqNumber;
52
53    fn sub(self, rhs: usize) -> SeqNumber {
54        if rhs > i32::MAX as usize {
55            panic!("attempt to subtract to sequence number with unsigned overflow")
56        }
57        SeqNumber(self.0.wrapping_sub(rhs as i32))
58    }
59}
60
61impl ops::AddAssign<usize> for SeqNumber {
62    fn add_assign(&mut self, rhs: usize) {
63        *self = *self + rhs;
64    }
65}
66
67impl ops::Sub for SeqNumber {
68    type Output = usize;
69
70    fn sub(self, rhs: SeqNumber) -> usize {
71        let result = self.0.wrapping_sub(rhs.0);
72        if result < 0 {
73            panic!("attempt to subtract sequence numbers with underflow")
74        }
75        result as usize
76    }
77}
78
79impl cmp::PartialOrd for SeqNumber {
80    fn partial_cmp(&self, other: &SeqNumber) -> Option<cmp::Ordering> {
81        self.0.wrapping_sub(other.0).partial_cmp(&0)
82    }
83}
84
85/// A read/write wrapper around a Transmission Control Protocol packet buffer.
86#[derive(Debug, PartialEq, Eq, Clone)]
87#[cfg_attr(feature = "defmt", derive(defmt::Format))]
88pub struct Packet<T: AsRef<[u8]>> {
89    buffer: T,
90}
91
92mod field {
93    #![allow(non_snake_case)]
94
95    use crate::wire::field::*;
96
97    pub const SRC_PORT: Field = 0..2;
98    pub const DST_PORT: Field = 2..4;
99    pub const SEQ_NUM: Field = 4..8;
100    pub const ACK_NUM: Field = 8..12;
101    pub const FLAGS: Field = 12..14;
102    pub const WIN_SIZE: Field = 14..16;
103    pub const CHECKSUM: Field = 16..18;
104    pub const URGENT: Field = 18..20;
105
106    pub const fn OPTIONS(length: u8) -> Field {
107        URGENT.end..(length as usize)
108    }
109
110    pub const FLG_FIN: u16 = 0x001;
111    pub const FLG_SYN: u16 = 0x002;
112    pub const FLG_RST: u16 = 0x004;
113    pub const FLG_PSH: u16 = 0x008;
114    pub const FLG_ACK: u16 = 0x010;
115    pub const FLG_URG: u16 = 0x020;
116    pub const FLG_ECE: u16 = 0x040;
117    pub const FLG_CWR: u16 = 0x080;
118    pub const FLG_NS: u16 = 0x100;
119
120    pub const OPT_END: u8 = 0x00;
121    pub const OPT_NOP: u8 = 0x01;
122    pub const OPT_MSS: u8 = 0x02;
123    pub const OPT_WS: u8 = 0x03;
124    pub const OPT_SACKPERM: u8 = 0x04;
125    pub const OPT_SACKRNG: u8 = 0x05;
126    pub const OPT_TSTAMP: u8 = 0x08;
127}
128
129pub const HEADER_LEN: usize = field::URGENT.end;
130
131impl<T: AsRef<[u8]>> Packet<T> {
132    /// Imbue a raw octet buffer with TCP packet structure.
133    pub const fn new_unchecked(buffer: T) -> Packet<T> {
134        Packet { buffer }
135    }
136
137    /// Shorthand for a combination of [new_unchecked] and [check_len].
138    ///
139    /// [new_unchecked]: #method.new_unchecked
140    /// [check_len]: #method.check_len
141    pub fn new_checked(buffer: T) -> Result<Packet<T>> {
142        let packet = Self::new_unchecked(buffer);
143        packet.check_len()?;
144        Ok(packet)
145    }
146
147    /// Ensure that no accessor method will panic if called.
148    /// Returns `Err(Error)` if the buffer is too short.
149    /// Returns `Err(Error)` if the header length field has a value smaller
150    /// than the minimal header length.
151    ///
152    /// The result of this check is invalidated by calling [set_header_len].
153    ///
154    /// [set_header_len]: #method.set_header_len
155    pub fn check_len(&self) -> Result<()> {
156        let len = self.buffer.as_ref().len();
157        if len < field::URGENT.end {
158            Err(Error)
159        } else {
160            let header_len = self.header_len() as usize;
161            if len < header_len || header_len < field::URGENT.end {
162                Err(Error)
163            } else {
164                Ok(())
165            }
166        }
167    }
168
169    /// Consume the packet, returning the underlying buffer.
170    pub fn into_inner(self) -> T {
171        self.buffer
172    }
173
174    /// Return the source port field.
175    #[inline]
176    pub fn src_port(&self) -> u16 {
177        let data = self.buffer.as_ref();
178        NetworkEndian::read_u16(&data[field::SRC_PORT])
179    }
180
181    /// Return the destination port field.
182    #[inline]
183    pub fn dst_port(&self) -> u16 {
184        let data = self.buffer.as_ref();
185        NetworkEndian::read_u16(&data[field::DST_PORT])
186    }
187
188    /// Return the sequence number field.
189    #[inline]
190    pub fn seq_number(&self) -> SeqNumber {
191        let data = self.buffer.as_ref();
192        SeqNumber(NetworkEndian::read_i32(&data[field::SEQ_NUM]))
193    }
194
195    /// Return the acknowledgement number field.
196    #[inline]
197    pub fn ack_number(&self) -> SeqNumber {
198        let data = self.buffer.as_ref();
199        SeqNumber(NetworkEndian::read_i32(&data[field::ACK_NUM]))
200    }
201
202    /// Return the FIN flag.
203    #[inline]
204    pub fn fin(&self) -> bool {
205        let data = self.buffer.as_ref();
206        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
207        raw & field::FLG_FIN != 0
208    }
209
210    /// Return the SYN flag.
211    #[inline]
212    pub fn syn(&self) -> bool {
213        let data = self.buffer.as_ref();
214        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
215        raw & field::FLG_SYN != 0
216    }
217
218    /// Return the RST flag.
219    #[inline]
220    pub fn rst(&self) -> bool {
221        let data = self.buffer.as_ref();
222        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
223        raw & field::FLG_RST != 0
224    }
225
226    /// Return the PSH flag.
227    #[inline]
228    pub fn psh(&self) -> bool {
229        let data = self.buffer.as_ref();
230        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
231        raw & field::FLG_PSH != 0
232    }
233
234    /// Return the ACK flag.
235    #[inline]
236    pub fn ack(&self) -> bool {
237        let data = self.buffer.as_ref();
238        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
239        raw & field::FLG_ACK != 0
240    }
241
242    /// Return the URG flag.
243    #[inline]
244    pub fn urg(&self) -> bool {
245        let data = self.buffer.as_ref();
246        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
247        raw & field::FLG_URG != 0
248    }
249
250    /// Return the ECE flag.
251    #[inline]
252    pub fn ece(&self) -> bool {
253        let data = self.buffer.as_ref();
254        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
255        raw & field::FLG_ECE != 0
256    }
257
258    /// Return the CWR flag.
259    #[inline]
260    pub fn cwr(&self) -> bool {
261        let data = self.buffer.as_ref();
262        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
263        raw & field::FLG_CWR != 0
264    }
265
266    /// Return the NS flag.
267    #[inline]
268    pub fn ns(&self) -> bool {
269        let data = self.buffer.as_ref();
270        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
271        raw & field::FLG_NS != 0
272    }
273
274    /// Return the header length, in octets.
275    #[inline]
276    pub fn header_len(&self) -> u8 {
277        let data = self.buffer.as_ref();
278        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
279        ((raw >> 12) * 4) as u8
280    }
281
282    /// Return the window size field.
283    #[inline]
284    pub fn window_len(&self) -> u16 {
285        let data = self.buffer.as_ref();
286        NetworkEndian::read_u16(&data[field::WIN_SIZE])
287    }
288
289    /// Return the checksum field.
290    #[inline]
291    pub fn checksum(&self) -> u16 {
292        let data = self.buffer.as_ref();
293        NetworkEndian::read_u16(&data[field::CHECKSUM])
294    }
295
296    /// Return the urgent pointer field.
297    #[inline]
298    pub fn urgent_at(&self) -> u16 {
299        let data = self.buffer.as_ref();
300        NetworkEndian::read_u16(&data[field::URGENT])
301    }
302
303    /// Return the length of the segment, in terms of sequence space.
304    pub fn segment_len(&self) -> usize {
305        let data = self.buffer.as_ref();
306        let mut length = data.len() - self.header_len() as usize;
307        if self.syn() {
308            length += 1
309        }
310        if self.fin() {
311            length += 1
312        }
313        length
314    }
315
316    /// Returns whether the selective acknowledgement SYN flag is set or not.
317    pub fn selective_ack_permitted(&self) -> Result<bool> {
318        let data = self.buffer.as_ref();
319        let mut options = &data[field::OPTIONS(self.header_len())];
320        while !options.is_empty() {
321            let (next_options, option) = TcpOption::parse(options)?;
322            if option == TcpOption::SackPermitted {
323                return Ok(true);
324            }
325            options = next_options;
326        }
327        Ok(false)
328    }
329
330    /// Return the selective acknowledgement ranges, if any. If there are none in the packet, an
331    /// array of ``None`` values will be returned.
332    ///
333    pub fn selective_ack_ranges(&self) -> Result<[Option<(u32, u32)>; 3]> {
334        let data = self.buffer.as_ref();
335        let mut options = &data[field::OPTIONS(self.header_len())];
336        while !options.is_empty() {
337            let (next_options, option) = TcpOption::parse(options)?;
338            if let TcpOption::SackRange(slice) = option {
339                return Ok(slice);
340            }
341            options = next_options;
342        }
343        Ok([None, None, None])
344    }
345
346    /// Parse and summarize all TCP options in a single pass.
347    pub fn options_summary(&self) -> Result<TcpOptionSummary> {
348        let data = self.buffer.as_ref();
349        let mut options = &data[field::OPTIONS(self.header_len())];
350        let mut summary = TcpOptionSummary::default();
351        while !options.is_empty() {
352            let (next_options, option) = TcpOption::parse(options)?;
353            match option {
354                TcpOption::EndOfList => break,
355                TcpOption::NoOperation => {}
356                TcpOption::MaxSegmentSize(mss) => summary.max_segment_size = Some(mss),
357                TcpOption::WindowScale(ws) => summary.window_scale = Some(ws),
358                TcpOption::SackPermitted => summary.sack_permitted = true,
359                TcpOption::SackRange(ranges) => summary.sack_ranges = ranges,
360                TcpOption::TimeStamp { tsval, tsecr } => summary.timestamp = Some((tsval, tsecr)),
361                TcpOption::Unknown { .. } => {}
362            }
363            options = next_options;
364        }
365        Ok(summary)
366    }
367
368    /// Validate the partial checksum.
369    ///
370    /// # Panics
371    /// This function panics unless `src_addr` and `dst_addr` belong to the same family,
372    /// and that family is IPv4 or IPv6.
373    ///
374    /// # Fuzzing
375    /// This function always returns `true` when fuzzing.
376    pub fn verify_partial_checksum(&self, src_addr: &IpAddress, dst_addr: &IpAddress) -> bool {
377        if cfg!(fuzzing) {
378            return true;
379        }
380
381        let data = self.buffer.as_ref();
382
383        checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp, data.len() as u32)
384            == self.checksum()
385    }
386
387    /// Validate the packet checksum.
388    ///
389    /// # Panics
390    /// This function panics unless `src_addr` and `dst_addr` belong to the same family,
391    /// and that family is IPv4 or IPv6.
392    ///
393    /// # Fuzzing
394    /// This function always returns `true` when fuzzing.
395    pub fn verify_checksum(&self, src_addr: &IpAddress, dst_addr: &IpAddress) -> bool {
396        if cfg!(fuzzing) {
397            return true;
398        }
399
400        let data = self.buffer.as_ref();
401        checksum::combine(&[
402            checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp, data.len() as u32),
403            checksum::data(data),
404        ]) == !0
405    }
406}
407
408impl<'a, T: AsRef<[u8]> + ?Sized> Packet<&'a T> {
409    /// Return a pointer to the options.
410    #[inline]
411    pub fn options(&self) -> &'a [u8] {
412        let header_len = self.header_len();
413        let data = self.buffer.as_ref();
414        &data[field::OPTIONS(header_len)]
415    }
416
417    /// Return a pointer to the payload.
418    #[inline]
419    pub fn payload(&self) -> &'a [u8] {
420        let header_len = self.header_len() as usize;
421        let data = self.buffer.as_ref();
422        &data[header_len..]
423    }
424}
425
426impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
427    /// Set the source port field.
428    #[inline]
429    pub fn set_src_port(&mut self, value: u16) {
430        let data = self.buffer.as_mut();
431        NetworkEndian::write_u16(&mut data[field::SRC_PORT], value)
432    }
433
434    /// Set the destination port field.
435    #[inline]
436    pub fn set_dst_port(&mut self, value: u16) {
437        let data = self.buffer.as_mut();
438        NetworkEndian::write_u16(&mut data[field::DST_PORT], value)
439    }
440
441    /// Set the sequence number field.
442    #[inline]
443    pub fn set_seq_number(&mut self, value: SeqNumber) {
444        let data = self.buffer.as_mut();
445        NetworkEndian::write_i32(&mut data[field::SEQ_NUM], value.0)
446    }
447
448    /// Set the acknowledgement number field.
449    #[inline]
450    pub fn set_ack_number(&mut self, value: SeqNumber) {
451        let data = self.buffer.as_mut();
452        NetworkEndian::write_i32(&mut data[field::ACK_NUM], value.0)
453    }
454
455    /// Clear the entire flags field.
456    #[inline]
457    pub fn clear_flags(&mut self) {
458        let data = self.buffer.as_mut();
459        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
460        let raw = raw & !0x0fff;
461        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
462    }
463
464    /// Set the FIN flag.
465    #[inline]
466    pub fn set_fin(&mut self, value: bool) {
467        let data = self.buffer.as_mut();
468        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
469        let raw = if value {
470            raw | field::FLG_FIN
471        } else {
472            raw & !field::FLG_FIN
473        };
474        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
475    }
476
477    /// Set the SYN flag.
478    #[inline]
479    pub fn set_syn(&mut self, value: bool) {
480        let data = self.buffer.as_mut();
481        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
482        let raw = if value {
483            raw | field::FLG_SYN
484        } else {
485            raw & !field::FLG_SYN
486        };
487        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
488    }
489
490    /// Set the RST flag.
491    #[inline]
492    pub fn set_rst(&mut self, value: bool) {
493        let data = self.buffer.as_mut();
494        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
495        let raw = if value {
496            raw | field::FLG_RST
497        } else {
498            raw & !field::FLG_RST
499        };
500        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
501    }
502
503    /// Set the PSH flag.
504    #[inline]
505    pub fn set_psh(&mut self, value: bool) {
506        let data = self.buffer.as_mut();
507        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
508        let raw = if value {
509            raw | field::FLG_PSH
510        } else {
511            raw & !field::FLG_PSH
512        };
513        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
514    }
515
516    /// Set the ACK flag.
517    #[inline]
518    pub fn set_ack(&mut self, value: bool) {
519        let data = self.buffer.as_mut();
520        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
521        let raw = if value {
522            raw | field::FLG_ACK
523        } else {
524            raw & !field::FLG_ACK
525        };
526        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
527    }
528
529    /// Set the URG flag.
530    #[inline]
531    pub fn set_urg(&mut self, value: bool) {
532        let data = self.buffer.as_mut();
533        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
534        let raw = if value {
535            raw | field::FLG_URG
536        } else {
537            raw & !field::FLG_URG
538        };
539        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
540    }
541
542    /// Set the ECE flag.
543    #[inline]
544    pub fn set_ece(&mut self, value: bool) {
545        let data = self.buffer.as_mut();
546        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
547        let raw = if value {
548            raw | field::FLG_ECE
549        } else {
550            raw & !field::FLG_ECE
551        };
552        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
553    }
554
555    /// Set the CWR flag.
556    #[inline]
557    pub fn set_cwr(&mut self, value: bool) {
558        let data = self.buffer.as_mut();
559        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
560        let raw = if value {
561            raw | field::FLG_CWR
562        } else {
563            raw & !field::FLG_CWR
564        };
565        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
566    }
567
568    /// Set the NS flag.
569    #[inline]
570    pub fn set_ns(&mut self, value: bool) {
571        let data = self.buffer.as_mut();
572        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
573        let raw = if value {
574            raw | field::FLG_NS
575        } else {
576            raw & !field::FLG_NS
577        };
578        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
579    }
580
581    /// Set the header length, in octets.
582    #[inline]
583    pub fn set_header_len(&mut self, value: u8) {
584        let data = self.buffer.as_mut();
585        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
586        let raw = (raw & !0xf000) | ((value as u16) / 4) << 12;
587        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
588    }
589
590    /// Set the window size field.
591    #[inline]
592    pub fn set_window_len(&mut self, value: u16) {
593        let data = self.buffer.as_mut();
594        NetworkEndian::write_u16(&mut data[field::WIN_SIZE], value)
595    }
596
597    /// Set the checksum field.
598    #[inline]
599    pub fn set_checksum(&mut self, value: u16) {
600        let data = self.buffer.as_mut();
601        NetworkEndian::write_u16(&mut data[field::CHECKSUM], value)
602    }
603
604    /// Set the urgent pointer field.
605    #[inline]
606    pub fn set_urgent_at(&mut self, value: u16) {
607        let data = self.buffer.as_mut();
608        NetworkEndian::write_u16(&mut data[field::URGENT], value)
609    }
610
611    /// Compute and fill in the header checksum.
612    ///
613    /// # Panics
614    /// This function panics unless `src_addr` and `dst_addr` belong to the same family,
615    /// and that family is IPv4 or IPv6.
616    pub fn fill_checksum(&mut self, src_addr: &IpAddress, dst_addr: &IpAddress) {
617        self.set_checksum(0);
618        let checksum = {
619            let data = self.buffer.as_ref();
620            !checksum::combine(&[
621                checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp, data.len() as u32),
622                checksum::data(data),
623            ])
624        };
625        self.set_checksum(checksum)
626    }
627
628    /// Return a pointer to the options.
629    #[inline]
630    pub fn options_mut(&mut self) -> &mut [u8] {
631        let header_len = self.header_len();
632        let data = self.buffer.as_mut();
633        &mut data[field::OPTIONS(header_len)]
634    }
635
636    /// Return a mutable pointer to the payload data.
637    #[inline]
638    pub fn payload_mut(&mut self) -> &mut [u8] {
639        let header_len = self.header_len() as usize;
640        let data = self.buffer.as_mut();
641        &mut data[header_len..]
642    }
643}
644
645impl<T: AsRef<[u8]>> AsRef<[u8]> for Packet<T> {
646    fn as_ref(&self) -> &[u8] {
647        self.buffer.as_ref()
648    }
649}
650
651/// A summary of all standard options contained in a TCP header.
652#[non_exhaustive]
653#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
654#[cfg_attr(feature = "defmt", derive(defmt::Format))]
655pub struct TcpOptionSummary {
656    pub max_segment_size: Option<u16>,
657    pub window_scale: Option<u8>,
658    pub sack_permitted: bool,
659    pub sack_ranges: [Option<(u32, u32)>; 3],
660    pub timestamp: Option<(u32, u32)>,
661}
662
663/// A representation of a single TCP option.
664#[derive(Debug, PartialEq, Eq, Clone, Copy)]
665#[cfg_attr(feature = "defmt", derive(defmt::Format))]
666pub enum TcpOption<'a> {
667    EndOfList,
668    NoOperation,
669    MaxSegmentSize(u16),
670    WindowScale(u8),
671    SackPermitted,
672    SackRange([Option<(u32, u32)>; 3]),
673    TimeStamp { tsval: u32, tsecr: u32 },
674    Unknown { kind: u8, data: &'a [u8] },
675}
676
677impl<'a> TcpOption<'a> {
678    pub fn parse(buffer: &'a [u8]) -> Result<(&'a [u8], TcpOption<'a>)> {
679        let (length, option);
680        match *buffer.first().ok_or(Error)? {
681            field::OPT_END => {
682                length = 1;
683                option = TcpOption::EndOfList;
684            }
685            field::OPT_NOP => {
686                length = 1;
687                option = TcpOption::NoOperation;
688            }
689            kind => {
690                length = *buffer.get(1).ok_or(Error)? as usize;
691                let data = buffer.get(2..length).ok_or(Error)?;
692                match (kind, length) {
693                    (field::OPT_END, _) | (field::OPT_NOP, _) => unreachable!(),
694                    (field::OPT_MSS, 4) => {
695                        option = TcpOption::MaxSegmentSize(NetworkEndian::read_u16(data))
696                    }
697                    (field::OPT_MSS, _) => return Err(Error),
698                    (field::OPT_WS, 3) => option = TcpOption::WindowScale(data[0]),
699                    (field::OPT_WS, _) => return Err(Error),
700                    (field::OPT_SACKPERM, 2) => option = TcpOption::SackPermitted,
701                    (field::OPT_SACKPERM, _) => return Err(Error),
702                    (field::OPT_SACKRNG, n) => {
703                        if n < 10 || (n - 2) % 8 != 0 {
704                            return Err(Error);
705                        }
706                        if n > 26 {
707                            // It's possible for a remote to send 4 SACK blocks, but extremely rare.
708                            // Better to "lose" that 4th block and save the extra RAM and CPU
709                            // cycles in the vastly more common case.
710                            //
711                            // RFC 2018: SACK option that specifies n blocks will have a length of
712                            // 8*n+2 bytes, so the 40 bytes available for TCP options can specify a
713                            // maximum of 4 blocks.  It is expected that SACK will often be used in
714                            // conjunction with the Timestamp option used for RTTM [...] thus a
715                            // maximum of 3 SACK blocks will be allowed in this case.
716                            net_debug!("sACK with >3 blocks, truncating to 3");
717                        }
718                        let mut sack_ranges: [Option<(u32, u32)>; 3] = [None; 3];
719
720                        // RFC 2018: Each contiguous block of data queued at the data receiver is
721                        // defined in the SACK option by two 32-bit unsigned integers in network
722                        // byte order[...]
723                        sack_ranges.iter_mut().enumerate().for_each(|(i, nmut)| {
724                            let left = i * 8;
725                            *nmut = if left < data.len() {
726                                let mid = left + 4;
727                                let right = mid + 4;
728                                let range_left = NetworkEndian::read_u32(&data[left..mid]);
729                                let range_right = NetworkEndian::read_u32(&data[mid..right]);
730                                Some((range_left, range_right))
731                            } else {
732                                None
733                            };
734                        });
735                        option = TcpOption::SackRange(sack_ranges);
736                    }
737                    (field::OPT_TSTAMP, 10) => {
738                        let tsval = NetworkEndian::read_u32(&data[0..4]);
739                        let tsecr = NetworkEndian::read_u32(&data[4..8]);
740                        option = TcpOption::TimeStamp { tsval, tsecr };
741                    }
742                    (_, _) => option = TcpOption::Unknown { kind, data },
743                }
744            }
745        }
746        Ok((&buffer[length..], option))
747    }
748
749    pub fn buffer_len(&self) -> usize {
750        match *self {
751            TcpOption::EndOfList => 1,
752            TcpOption::NoOperation => 1,
753            TcpOption::MaxSegmentSize(_) => 4,
754            TcpOption::WindowScale(_) => 3,
755            TcpOption::SackPermitted => 2,
756            TcpOption::SackRange(s) => s.iter().filter(|s| s.is_some()).count() * 8 + 2,
757            TcpOption::TimeStamp { tsval: _, tsecr: _ } => 10,
758            TcpOption::Unknown { data, .. } => 2 + data.len(),
759        }
760    }
761
762    pub fn emit<'b>(&self, buffer: &'b mut [u8]) -> &'b mut [u8] {
763        let length;
764        match *self {
765            TcpOption::EndOfList => {
766                length = 1;
767                // There may be padding space which also should be initialized.
768                for p in buffer.iter_mut() {
769                    *p = field::OPT_END;
770                }
771            }
772            TcpOption::NoOperation => {
773                length = 1;
774                buffer[0] = field::OPT_NOP;
775            }
776            _ => {
777                length = self.buffer_len();
778                buffer[1] = length as u8;
779                match self {
780                    &TcpOption::EndOfList | &TcpOption::NoOperation => unreachable!(),
781                    &TcpOption::MaxSegmentSize(value) => {
782                        buffer[0] = field::OPT_MSS;
783                        NetworkEndian::write_u16(&mut buffer[2..], value)
784                    }
785                    &TcpOption::WindowScale(value) => {
786                        buffer[0] = field::OPT_WS;
787                        buffer[2] = value;
788                    }
789                    &TcpOption::SackPermitted => {
790                        buffer[0] = field::OPT_SACKPERM;
791                    }
792                    &TcpOption::SackRange(slice) => {
793                        buffer[0] = field::OPT_SACKRNG;
794                        slice
795                            .iter()
796                            .filter(|s| s.is_some())
797                            .enumerate()
798                            .for_each(|(i, s)| {
799                                let (first, second) = *s.as_ref().unwrap();
800                                let pos = i * 8 + 2;
801                                NetworkEndian::write_u32(&mut buffer[pos..], first);
802                                NetworkEndian::write_u32(&mut buffer[pos + 4..], second);
803                            });
804                    }
805                    &TcpOption::TimeStamp { tsval, tsecr } => {
806                        buffer[0] = field::OPT_TSTAMP;
807                        NetworkEndian::write_u32(&mut buffer[2..], tsval);
808                        NetworkEndian::write_u32(&mut buffer[6..], tsecr);
809                    }
810                    &TcpOption::Unknown {
811                        kind,
812                        data: provided,
813                    } => {
814                        buffer[0] = kind;
815                        buffer[2..].copy_from_slice(provided)
816                    }
817                }
818            }
819        }
820        &mut buffer[length..]
821    }
822}
823
824/// The possible control flags of a Transmission Control Protocol packet.
825#[derive(Debug, PartialEq, Eq, Clone, Copy)]
826#[cfg_attr(feature = "defmt", derive(defmt::Format))]
827pub enum Control {
828    None,
829    Psh,
830    Syn,
831    Fin,
832    Rst,
833}
834
835#[allow(clippy::len_without_is_empty)]
836impl Control {
837    /// Return the length of a control flag, in terms of sequence space.
838    pub const fn len(self) -> usize {
839        match self {
840            Control::Syn | Control::Fin => 1,
841            _ => 0,
842        }
843    }
844
845    /// Turn the PSH flag into no flag, and keep the rest as-is.
846    pub const fn quash_psh(self) -> Control {
847        match self {
848            Control::Psh => Control::None,
849            _ => self,
850        }
851    }
852}
853
854/// A high-level representation of a Transmission Control Protocol packet.
855#[derive(Debug, PartialEq, Eq, Clone, Copy)]
856pub struct Repr<'a> {
857    pub src_port: u16,
858    pub dst_port: u16,
859    pub control: Control,
860    pub seq_number: SeqNumber,
861    pub ack_number: Option<SeqNumber>,
862    pub window_len: u16,
863    pub window_scale: Option<u8>,
864    pub max_seg_size: Option<u16>,
865    pub sack_permitted: bool,
866    pub sack_ranges: [Option<(u32, u32)>; 3],
867    pub timestamp: Option<TcpTimestampRepr>,
868    pub payload: &'a [u8],
869}
870
871pub type TcpTimestampGenerator = fn() -> u32;
872
873#[derive(Debug, PartialEq, Eq, Clone, Copy)]
874pub struct TcpTimestampRepr {
875    pub tsval: u32,
876    pub tsecr: u32,
877}
878
879impl TcpTimestampRepr {
880    pub fn new(tsval: u32, tsecr: u32) -> Self {
881        Self { tsval, tsecr }
882    }
883
884    pub fn generate_reply(&self, generator: Option<TcpTimestampGenerator>) -> Option<Self> {
885        Self::generate_reply_with_tsval(generator, self.tsval)
886    }
887
888    pub fn generate_reply_with_tsval(
889        generator: Option<TcpTimestampGenerator>,
890        tsval: u32,
891    ) -> Option<Self> {
892        Some(Self::new(generator?(), tsval))
893    }
894}
895
896impl<'a> Repr<'a> {
897    /// Parse a Transmission Control Protocol packet and return a high-level representation.
898    pub fn parse<T>(
899        packet: &Packet<&'a T>,
900        src_addr: &IpAddress,
901        dst_addr: &IpAddress,
902        checksum_caps: &ChecksumCapabilities,
903    ) -> Result<Repr<'a>>
904    where
905        T: AsRef<[u8]> + ?Sized,
906    {
907        packet.check_len()?;
908
909        // Source and destination ports must be present.
910        if packet.src_port() == 0 {
911            return Err(Error);
912        }
913        if packet.dst_port() == 0 {
914            return Err(Error);
915        }
916        // Valid checksum is expected.
917        if checksum_caps.tcp.rx() && !packet.verify_checksum(src_addr, dst_addr) {
918            return Err(Error);
919        }
920
921        let control = match (packet.syn(), packet.fin(), packet.rst(), packet.psh()) {
922            (false, false, false, false) => Control::None,
923            (false, false, false, true) => Control::Psh,
924            (true, false, false, _) => Control::Syn,
925            (false, true, false, _) => Control::Fin,
926            (false, false, true, _) => Control::Rst,
927            _ => return Err(Error),
928        };
929        let ack_number = match packet.ack() {
930            true => Some(packet.ack_number()),
931            false => None,
932        };
933        // The PSH flag is ignored.
934        // The URG flag and the urgent field is ignored. This behavior is standards-compliant,
935        // however, most deployed systems (e.g. Linux) are *not* standards-compliant, and would
936        // cut the byte at the urgent pointer from the stream.
937
938        let mut max_seg_size = None;
939        let mut window_scale = None;
940        let mut options = packet.options();
941        let mut sack_permitted = false;
942        let mut sack_ranges = [None, None, None];
943        let mut timestamp = None;
944        while !options.is_empty() {
945            let (next_options, option) = TcpOption::parse(options)?;
946            match option {
947                TcpOption::EndOfList => break,
948                TcpOption::NoOperation => (),
949                TcpOption::MaxSegmentSize(value) => max_seg_size = Some(value),
950                TcpOption::WindowScale(value) => {
951                    // RFC 1323: Thus, the shift count must be limited to 14 (which allows windows
952                    // of 2**30 = 1 Gigabyte). If a Window Scale option is received with a shift.cnt
953                    // value exceeding 14, the TCP should log the error but use 14 instead of the
954                    // specified value.
955                    window_scale = if value > 14 {
956                        net_debug!(
957                            "{}:{}:{}:{}: parsed window scaling factor >14, setting to 14",
958                            src_addr,
959                            packet.src_port(),
960                            dst_addr,
961                            packet.dst_port()
962                        );
963                        Some(14)
964                    } else {
965                        Some(value)
966                    };
967                }
968                TcpOption::SackPermitted => sack_permitted = true,
969                TcpOption::SackRange(slice) => sack_ranges = slice,
970                TcpOption::TimeStamp { tsval, tsecr } => {
971                    timestamp = Some(TcpTimestampRepr::new(tsval, tsecr));
972                }
973                _ => (),
974            }
975            options = next_options;
976        }
977
978        Ok(Repr {
979            src_port: packet.src_port(),
980            dst_port: packet.dst_port(),
981            control: control,
982            seq_number: packet.seq_number(),
983            ack_number: ack_number,
984            window_len: packet.window_len(),
985            window_scale: window_scale,
986            max_seg_size: max_seg_size,
987            sack_permitted: sack_permitted,
988            sack_ranges: sack_ranges,
989            timestamp: timestamp,
990            payload: packet.payload(),
991        })
992    }
993
994    /// Return the length of a header that will be emitted from this high-level representation.
995    ///
996    /// This should be used for buffer space calculations.
997    /// The TCP header length is a multiple of 4.
998    pub fn header_len(&self) -> usize {
999        let mut length = field::URGENT.end;
1000        if self.max_seg_size.is_some() {
1001            length += 4
1002        }
1003        if self.window_scale.is_some() {
1004            length += 3
1005        }
1006        if self.sack_permitted {
1007            length += 2;
1008        }
1009        if self.timestamp.is_some() {
1010            length += 10;
1011        }
1012        let sack_range_len: usize = self
1013            .sack_ranges
1014            .iter()
1015            .map(|o| o.map(|_| 8).unwrap_or(0))
1016            .sum();
1017        if sack_range_len > 0 {
1018            length += sack_range_len + 2;
1019        }
1020        if !length.is_multiple_of(4) {
1021            length += 4 - length % 4;
1022        }
1023        length
1024    }
1025
1026    /// Return the length of a packet that will be emitted from this high-level representation.
1027    pub fn buffer_len(&self) -> usize {
1028        self.header_len() + self.payload.len()
1029    }
1030
1031    /// Emit a high-level representation into a Transmission Control Protocol packet.
1032    pub fn emit<T>(
1033        &self,
1034        packet: &mut Packet<&mut T>,
1035        src_addr: &IpAddress,
1036        dst_addr: &IpAddress,
1037        checksum_caps: &ChecksumCapabilities,
1038    ) where
1039        T: AsRef<[u8]> + AsMut<[u8]> + ?Sized,
1040    {
1041        packet.set_src_port(self.src_port);
1042        packet.set_dst_port(self.dst_port);
1043        packet.set_seq_number(self.seq_number);
1044        packet.set_ack_number(self.ack_number.unwrap_or(SeqNumber(0)));
1045        packet.set_window_len(self.window_len);
1046        packet.set_header_len(self.header_len() as u8);
1047        packet.clear_flags();
1048        match self.control {
1049            Control::None => (),
1050            Control::Psh => packet.set_psh(true),
1051            Control::Syn => packet.set_syn(true),
1052            Control::Fin => packet.set_fin(true),
1053            Control::Rst => packet.set_rst(true),
1054        }
1055        packet.set_ack(self.ack_number.is_some());
1056        {
1057            let mut options = packet.options_mut();
1058            if let Some(value) = self.max_seg_size {
1059                let tmp = options;
1060                options = TcpOption::MaxSegmentSize(value).emit(tmp);
1061            }
1062            if let Some(value) = self.window_scale {
1063                let tmp = options;
1064                options = TcpOption::WindowScale(value).emit(tmp);
1065            }
1066            if self.sack_permitted {
1067                let tmp = options;
1068                options = TcpOption::SackPermitted.emit(tmp);
1069            } else if self.ack_number.is_some() && self.sack_ranges.iter().any(|s| s.is_some()) {
1070                let tmp = options;
1071                options = TcpOption::SackRange(self.sack_ranges).emit(tmp);
1072            }
1073            if let Some(timestamp) = self.timestamp {
1074                let tmp = options;
1075                options = TcpOption::TimeStamp {
1076                    tsval: timestamp.tsval,
1077                    tsecr: timestamp.tsecr,
1078                }
1079                .emit(tmp);
1080            }
1081
1082            if !options.is_empty() {
1083                TcpOption::EndOfList.emit(options);
1084            }
1085        }
1086        packet.set_urgent_at(0);
1087        packet.payload_mut()[..self.payload.len()].copy_from_slice(self.payload);
1088
1089        if checksum_caps.tcp.tx() {
1090            packet.fill_checksum(src_addr, dst_addr)
1091        } else {
1092            // make sure we get a consistently zeroed checksum,
1093            // since implementations might rely on it
1094            packet.set_checksum(0);
1095        }
1096    }
1097
1098    /// Return the length of the segment, in terms of sequence space.
1099    pub const fn segment_len(&self) -> usize {
1100        self.payload.len() + self.control.len()
1101    }
1102
1103    /// Return whether the segment has no flags set (except PSH) and no data.
1104    pub const fn is_empty(&self) -> bool {
1105        match self.control {
1106            _ if !self.payload.is_empty() => false,
1107            Control::Syn | Control::Fin | Control::Rst => false,
1108            Control::None | Control::Psh => true,
1109        }
1110    }
1111}
1112
1113impl<T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&T> {
1114    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1115        // Cannot use Repr::parse because we don't have the IP addresses.
1116        write!(f, "TCP src={} dst={}", self.src_port(), self.dst_port())?;
1117        if self.syn() {
1118            write!(f, " syn")?
1119        }
1120        if self.fin() {
1121            write!(f, " fin")?
1122        }
1123        if self.rst() {
1124            write!(f, " rst")?
1125        }
1126        if self.psh() {
1127            write!(f, " psh")?
1128        }
1129        if self.ece() {
1130            write!(f, " ece")?
1131        }
1132        if self.cwr() {
1133            write!(f, " cwr")?
1134        }
1135        if self.ns() {
1136            write!(f, " ns")?
1137        }
1138        write!(f, " seq={}", self.seq_number())?;
1139        if self.ack() {
1140            write!(f, " ack={}", self.ack_number())?;
1141        }
1142        write!(f, " win={}", self.window_len())?;
1143        if self.urg() {
1144            write!(f, " urg={}", self.urgent_at())?;
1145        }
1146        write!(f, " len={}", self.payload().len())?;
1147
1148        let mut options = self.options();
1149        while !options.is_empty() {
1150            let (next_options, option) = match TcpOption::parse(options) {
1151                Ok(res) => res,
1152                Err(err) => return write!(f, " ({err})"),
1153            };
1154            match option {
1155                TcpOption::EndOfList => break,
1156                TcpOption::NoOperation => (),
1157                TcpOption::MaxSegmentSize(value) => write!(f, " mss={value}")?,
1158                TcpOption::WindowScale(value) => write!(f, " ws={value}")?,
1159                TcpOption::SackPermitted => write!(f, " sACK")?,
1160                TcpOption::SackRange(slice) => write!(f, " sACKr{slice:?}")?, // debug print conveniently includes the []s
1161                TcpOption::TimeStamp { tsval, tsecr } => {
1162                    write!(f, " tsval {tsval:08x} tsecr {tsecr:08x}")?
1163                }
1164                TcpOption::Unknown { kind, .. } => write!(f, " opt({kind})")?,
1165            }
1166            options = next_options;
1167        }
1168        Ok(())
1169    }
1170}
1171
1172impl<'a> fmt::Display for Repr<'a> {
1173    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1174        write!(f, "TCP src={} dst={}", self.src_port, self.dst_port)?;
1175        match self.control {
1176            Control::Syn => write!(f, " syn")?,
1177            Control::Fin => write!(f, " fin")?,
1178            Control::Rst => write!(f, " rst")?,
1179            Control::Psh => write!(f, " psh")?,
1180            Control::None => (),
1181        }
1182        write!(f, " seq={}", self.seq_number)?;
1183        if let Some(ack_number) = self.ack_number {
1184            write!(f, " ack={ack_number}")?;
1185        }
1186        write!(f, " win={}", self.window_len)?;
1187        write!(f, " len={}", self.payload.len())?;
1188        if let Some(max_seg_size) = self.max_seg_size {
1189            write!(f, " mss={max_seg_size}")?;
1190        }
1191        Ok(())
1192    }
1193}
1194
1195#[cfg(feature = "defmt")]
1196impl<'a> defmt::Format for Repr<'a> {
1197    fn format(&self, fmt: defmt::Formatter) {
1198        defmt::write!(fmt, "TCP src={} dst={}", self.src_port, self.dst_port);
1199        match self.control {
1200            Control::Syn => defmt::write!(fmt, " syn"),
1201            Control::Fin => defmt::write!(fmt, " fin"),
1202            Control::Rst => defmt::write!(fmt, " rst"),
1203            Control::Psh => defmt::write!(fmt, " psh"),
1204            Control::None => (),
1205        }
1206        defmt::write!(fmt, " seq={}", self.seq_number);
1207        if let Some(ack_number) = self.ack_number {
1208            defmt::write!(fmt, " ack={}", ack_number);
1209        }
1210        defmt::write!(fmt, " win={}", self.window_len);
1211        defmt::write!(fmt, " len={}", self.payload.len());
1212        if let Some(max_seg_size) = self.max_seg_size {
1213            defmt::write!(fmt, " mss={}", max_seg_size);
1214        }
1215    }
1216}
1217
1218use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
1219
1220impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
1221    fn pretty_print(
1222        buffer: &dyn AsRef<[u8]>,
1223        f: &mut fmt::Formatter,
1224        indent: &mut PrettyIndent,
1225    ) -> fmt::Result {
1226        match Packet::new_checked(buffer) {
1227            Err(err) => write!(f, "{indent}({err})"),
1228            Ok(packet) => write!(f, "{indent}{packet}"),
1229        }
1230    }
1231}
1232
1233#[cfg(test)]
1234mod test {
1235    use super::*;
1236    #[cfg(feature = "proto-ipv4")]
1237    use crate::wire::Ipv4Address;
1238
1239    #[cfg(feature = "proto-ipv4")]
1240    const SRC_ADDR: Ipv4Address = Ipv4Address::new(192, 168, 1, 1);
1241    #[cfg(feature = "proto-ipv4")]
1242    const DST_ADDR: Ipv4Address = Ipv4Address::new(192, 168, 1, 2);
1243
1244    #[cfg(feature = "proto-ipv4")]
1245    static PACKET_BYTES: [u8; 28] = [
1246        0xbf, 0x00, 0x00, 0x50, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x60, 0x35, 0x01,
1247        0x23, 0x01, 0xb6, 0x02, 0x01, 0x03, 0x03, 0x0c, 0x01, 0xaa, 0x00, 0x00, 0xff,
1248    ];
1249
1250    #[cfg(feature = "proto-ipv4")]
1251    static OPTION_BYTES: [u8; 4] = [0x03, 0x03, 0x0c, 0x01];
1252
1253    #[cfg(feature = "proto-ipv4")]
1254    static PAYLOAD_BYTES: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
1255
1256    #[test]
1257    #[cfg(feature = "proto-ipv4")]
1258    fn test_deconstruct() {
1259        let packet = Packet::new_unchecked(&PACKET_BYTES[..]);
1260        assert_eq!(packet.src_port(), 48896);
1261        assert_eq!(packet.dst_port(), 80);
1262        assert_eq!(packet.seq_number(), SeqNumber(0x01234567));
1263        assert_eq!(packet.ack_number(), SeqNumber(0x89abcdefu32 as i32));
1264        assert_eq!(packet.header_len(), 24);
1265        assert!(packet.fin());
1266        assert!(!packet.syn());
1267        assert!(packet.rst());
1268        assert!(!packet.psh());
1269        assert!(packet.ack());
1270        assert!(packet.urg());
1271        assert_eq!(packet.window_len(), 0x0123);
1272        assert_eq!(packet.urgent_at(), 0x0201);
1273        assert_eq!(packet.checksum(), 0x01b6);
1274        assert_eq!(packet.options(), &OPTION_BYTES[..]);
1275        assert_eq!(packet.payload(), &PAYLOAD_BYTES[..]);
1276        assert!(packet.verify_checksum(&SRC_ADDR.into(), &DST_ADDR.into()));
1277    }
1278
1279    #[test]
1280    #[cfg(feature = "proto-ipv4")]
1281    fn test_construct() {
1282        let mut bytes = vec![0xa5; PACKET_BYTES.len()];
1283        let mut packet = Packet::new_unchecked(&mut bytes);
1284        packet.set_src_port(48896);
1285        packet.set_dst_port(80);
1286        packet.set_seq_number(SeqNumber(0x01234567));
1287        packet.set_ack_number(SeqNumber(0x89abcdefu32 as i32));
1288        packet.set_header_len(24);
1289        packet.clear_flags();
1290        packet.set_fin(true);
1291        packet.set_syn(false);
1292        packet.set_rst(true);
1293        packet.set_psh(false);
1294        packet.set_ack(true);
1295        packet.set_urg(true);
1296        packet.set_window_len(0x0123);
1297        packet.set_urgent_at(0x0201);
1298        packet.set_checksum(0xEEEE);
1299        packet.options_mut().copy_from_slice(&OPTION_BYTES[..]);
1300        packet.payload_mut().copy_from_slice(&PAYLOAD_BYTES[..]);
1301        packet.fill_checksum(&SRC_ADDR.into(), &DST_ADDR.into());
1302        assert_eq!(&*packet.into_inner(), &PACKET_BYTES[..]);
1303    }
1304
1305    #[test]
1306    #[cfg(feature = "proto-ipv4")]
1307    fn test_truncated() {
1308        let packet = Packet::new_unchecked(&PACKET_BYTES[..23]);
1309        assert_eq!(packet.check_len(), Err(Error));
1310    }
1311
1312    #[test]
1313    fn test_impossible_len() {
1314        let mut bytes = vec![0; 20];
1315        let mut packet = Packet::new_unchecked(&mut bytes);
1316        packet.set_header_len(10);
1317        assert_eq!(packet.check_len(), Err(Error));
1318    }
1319
1320    #[cfg(feature = "proto-ipv4")]
1321    static SYN_PACKET_BYTES: [u8; 24] = [
1322        0xbf, 0x00, 0x00, 0x50, 0x01, 0x23, 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02, 0x01,
1323        0x23, 0x7a, 0x8d, 0x00, 0x00, 0xaa, 0x00, 0x00, 0xff,
1324    ];
1325
1326    #[cfg(feature = "proto-ipv4")]
1327    fn packet_repr() -> Repr<'static> {
1328        Repr {
1329            src_port: 48896,
1330            dst_port: 80,
1331            seq_number: SeqNumber(0x01234567),
1332            ack_number: None,
1333            window_len: 0x0123,
1334            window_scale: None,
1335            control: Control::Syn,
1336            max_seg_size: None,
1337            sack_permitted: false,
1338            sack_ranges: [None, None, None],
1339            timestamp: None,
1340            payload: &PAYLOAD_BYTES,
1341        }
1342    }
1343
1344    #[test]
1345    #[cfg(feature = "proto-ipv4")]
1346    fn test_parse() {
1347        let packet = Packet::new_unchecked(&SYN_PACKET_BYTES[..]);
1348        let repr = Repr::parse(
1349            &packet,
1350            &SRC_ADDR.into(),
1351            &DST_ADDR.into(),
1352            &ChecksumCapabilities::default(),
1353        )
1354        .unwrap();
1355        assert_eq!(repr, packet_repr());
1356    }
1357
1358    #[test]
1359    #[cfg(feature = "proto-ipv4")]
1360    fn test_emit() {
1361        let repr = packet_repr();
1362        let mut bytes = vec![0xa5; repr.buffer_len()];
1363        let mut packet = Packet::new_unchecked(&mut bytes);
1364        repr.emit(
1365            &mut packet,
1366            &SRC_ADDR.into(),
1367            &DST_ADDR.into(),
1368            &ChecksumCapabilities::default(),
1369        );
1370        assert_eq!(&*packet.into_inner(), &SYN_PACKET_BYTES[..]);
1371    }
1372
1373    #[test]
1374    #[cfg(feature = "proto-ipv4")]
1375    fn test_header_len_multiple_of_4() {
1376        let mut repr = packet_repr();
1377        repr.window_scale = Some(0); // This TCP Option needs 3 bytes.
1378        assert_eq!(repr.header_len() % 4, 0); // Should e.g. be 28 instead of 27.
1379    }
1380
1381    macro_rules! assert_option_parses {
1382        ($opt:expr, $data:expr) => {{
1383            assert_eq!(TcpOption::parse($data), Ok((&[][..], $opt)));
1384            let buffer = &mut [0; 40][..$opt.buffer_len()];
1385            assert_eq!($opt.emit(buffer), &mut []);
1386            assert_eq!(&*buffer, $data);
1387        }};
1388    }
1389
1390    #[test]
1391    fn test_tcp_options() {
1392        assert_option_parses!(TcpOption::EndOfList, &[0x00]);
1393        assert_option_parses!(TcpOption::NoOperation, &[0x01]);
1394        assert_option_parses!(TcpOption::MaxSegmentSize(1500), &[0x02, 0x04, 0x05, 0xdc]);
1395        assert_option_parses!(TcpOption::WindowScale(12), &[0x03, 0x03, 0x0c]);
1396        assert_option_parses!(TcpOption::SackPermitted, &[0x4, 0x02]);
1397        assert_option_parses!(
1398            TcpOption::SackRange([Some((500, 1500)), None, None]),
1399            &[0x05, 0x0a, 0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x05, 0xdc]
1400        );
1401        assert_option_parses!(
1402            TcpOption::SackRange([Some((875, 1225)), Some((1500, 2500)), None]),
1403            &[
1404                0x05, 0x12, 0x00, 0x00, 0x03, 0x6b, 0x00, 0x00, 0x04, 0xc9, 0x00, 0x00, 0x05, 0xdc,
1405                0x00, 0x00, 0x09, 0xc4
1406            ]
1407        );
1408        assert_option_parses!(
1409            TcpOption::SackRange([
1410                Some((875000, 1225000)),
1411                Some((1500000, 2500000)),
1412                Some((876543210, 876654320))
1413            ]),
1414            &[
1415                0x05, 0x1a, 0x00, 0x0d, 0x59, 0xf8, 0x00, 0x12, 0xb1, 0x28, 0x00, 0x16, 0xe3, 0x60,
1416                0x00, 0x26, 0x25, 0xa0, 0x34, 0x3e, 0xfc, 0xea, 0x34, 0x40, 0xae, 0xf0
1417            ]
1418        );
1419        assert_option_parses!(
1420            TcpOption::TimeStamp {
1421                tsval: 5000000,
1422                tsecr: 7000000
1423            },
1424            &[
1425                0x08, // data length
1426                0x0a, // type
1427                0x00, 0x4c, 0x4b, 0x40, //tsval
1428                0x00, 0x6a, 0xcf, 0xc0 //tsecr
1429            ]
1430        );
1431        assert_option_parses!(
1432            TcpOption::Unknown {
1433                kind: 12,
1434                data: &[1, 2, 3][..]
1435            },
1436            &[0x0c, 0x05, 0x01, 0x02, 0x03]
1437        )
1438    }
1439
1440    #[test]
1441    fn test_malformed_tcp_options() {
1442        assert_eq!(TcpOption::parse(&[]), Err(Error));
1443        assert_eq!(TcpOption::parse(&[0xc]), Err(Error));
1444        assert_eq!(TcpOption::parse(&[0xc, 0x05, 0x01, 0x02]), Err(Error));
1445        assert_eq!(TcpOption::parse(&[0xc, 0x01]), Err(Error));
1446        assert_eq!(TcpOption::parse(&[0x2, 0x02]), Err(Error));
1447        assert_eq!(TcpOption::parse(&[0x3, 0x02]), Err(Error));
1448    }
1449
1450    #[test]
1451    fn test_tcp_options_summary() {
1452        let mut bytes = vec![0; 32];
1453        let mut packet = Packet::new_unchecked(&mut bytes);
1454        packet.set_header_len(32);
1455        // MSS=1460 (4b: 02 04 05 b4), WS=7 (3b: 03 03 07), SACK_PERM (2b: 04 02), NOP (1b: 01), END (1b: 00)
1456        let options_bytes: [u8; 12] = [
1457            0x02, 0x04, 0x05, 0xb4, 0x03, 0x03, 0x07, 0x04, 0x02, 0x01, 0x00, 0x00,
1458        ];
1459        packet.options_mut()[..12].copy_from_slice(&options_bytes);
1460
1461        let summary = packet.options_summary().unwrap();
1462        assert_eq!(summary.max_segment_size, Some(1460));
1463        assert_eq!(summary.window_scale, Some(7));
1464        assert!(summary.sack_permitted);
1465        assert_eq!(summary.sack_ranges, [None, None, None]);
1466    }
1467}