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    /// Validate the partial checksum.
347    ///
348    /// # Panics
349    /// This function panics unless `src_addr` and `dst_addr` belong to the same family,
350    /// and that family is IPv4 or IPv6.
351    ///
352    /// # Fuzzing
353    /// This function always returns `true` when fuzzing.
354    pub fn verify_partial_checksum(&self, src_addr: &IpAddress, dst_addr: &IpAddress) -> bool {
355        if cfg!(fuzzing) {
356            return true;
357        }
358
359        let data = self.buffer.as_ref();
360
361        checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp, data.len() as u32)
362            == self.checksum()
363    }
364
365    /// Validate the packet checksum.
366    ///
367    /// # Panics
368    /// This function panics unless `src_addr` and `dst_addr` belong to the same family,
369    /// and that family is IPv4 or IPv6.
370    ///
371    /// # Fuzzing
372    /// This function always returns `true` when fuzzing.
373    pub fn verify_checksum(&self, src_addr: &IpAddress, dst_addr: &IpAddress) -> bool {
374        if cfg!(fuzzing) {
375            return true;
376        }
377
378        let data = self.buffer.as_ref();
379        checksum::combine(&[
380            checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp, data.len() as u32),
381            checksum::data(data),
382        ]) == !0
383    }
384}
385
386impl<'a, T: AsRef<[u8]> + ?Sized> Packet<&'a T> {
387    /// Return a pointer to the options.
388    #[inline]
389    pub fn options(&self) -> &'a [u8] {
390        let header_len = self.header_len();
391        let data = self.buffer.as_ref();
392        &data[field::OPTIONS(header_len)]
393    }
394
395    /// Return a pointer to the payload.
396    #[inline]
397    pub fn payload(&self) -> &'a [u8] {
398        let header_len = self.header_len() as usize;
399        let data = self.buffer.as_ref();
400        &data[header_len..]
401    }
402}
403
404impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
405    /// Set the source port field.
406    #[inline]
407    pub fn set_src_port(&mut self, value: u16) {
408        let data = self.buffer.as_mut();
409        NetworkEndian::write_u16(&mut data[field::SRC_PORT], value)
410    }
411
412    /// Set the destination port field.
413    #[inline]
414    pub fn set_dst_port(&mut self, value: u16) {
415        let data = self.buffer.as_mut();
416        NetworkEndian::write_u16(&mut data[field::DST_PORT], value)
417    }
418
419    /// Set the sequence number field.
420    #[inline]
421    pub fn set_seq_number(&mut self, value: SeqNumber) {
422        let data = self.buffer.as_mut();
423        NetworkEndian::write_i32(&mut data[field::SEQ_NUM], value.0)
424    }
425
426    /// Set the acknowledgement number field.
427    #[inline]
428    pub fn set_ack_number(&mut self, value: SeqNumber) {
429        let data = self.buffer.as_mut();
430        NetworkEndian::write_i32(&mut data[field::ACK_NUM], value.0)
431    }
432
433    /// Clear the entire flags field.
434    #[inline]
435    pub fn clear_flags(&mut self) {
436        let data = self.buffer.as_mut();
437        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
438        let raw = raw & !0x0fff;
439        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
440    }
441
442    /// Set the FIN flag.
443    #[inline]
444    pub fn set_fin(&mut self, value: bool) {
445        let data = self.buffer.as_mut();
446        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
447        let raw = if value {
448            raw | field::FLG_FIN
449        } else {
450            raw & !field::FLG_FIN
451        };
452        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
453    }
454
455    /// Set the SYN flag.
456    #[inline]
457    pub fn set_syn(&mut self, value: bool) {
458        let data = self.buffer.as_mut();
459        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
460        let raw = if value {
461            raw | field::FLG_SYN
462        } else {
463            raw & !field::FLG_SYN
464        };
465        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
466    }
467
468    /// Set the RST flag.
469    #[inline]
470    pub fn set_rst(&mut self, value: bool) {
471        let data = self.buffer.as_mut();
472        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
473        let raw = if value {
474            raw | field::FLG_RST
475        } else {
476            raw & !field::FLG_RST
477        };
478        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
479    }
480
481    /// Set the PSH flag.
482    #[inline]
483    pub fn set_psh(&mut self, value: bool) {
484        let data = self.buffer.as_mut();
485        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
486        let raw = if value {
487            raw | field::FLG_PSH
488        } else {
489            raw & !field::FLG_PSH
490        };
491        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
492    }
493
494    /// Set the ACK flag.
495    #[inline]
496    pub fn set_ack(&mut self, value: bool) {
497        let data = self.buffer.as_mut();
498        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
499        let raw = if value {
500            raw | field::FLG_ACK
501        } else {
502            raw & !field::FLG_ACK
503        };
504        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
505    }
506
507    /// Set the URG flag.
508    #[inline]
509    pub fn set_urg(&mut self, value: bool) {
510        let data = self.buffer.as_mut();
511        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
512        let raw = if value {
513            raw | field::FLG_URG
514        } else {
515            raw & !field::FLG_URG
516        };
517        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
518    }
519
520    /// Set the ECE flag.
521    #[inline]
522    pub fn set_ece(&mut self, value: bool) {
523        let data = self.buffer.as_mut();
524        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
525        let raw = if value {
526            raw | field::FLG_ECE
527        } else {
528            raw & !field::FLG_ECE
529        };
530        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
531    }
532
533    /// Set the CWR flag.
534    #[inline]
535    pub fn set_cwr(&mut self, value: bool) {
536        let data = self.buffer.as_mut();
537        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
538        let raw = if value {
539            raw | field::FLG_CWR
540        } else {
541            raw & !field::FLG_CWR
542        };
543        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
544    }
545
546    /// Set the NS flag.
547    #[inline]
548    pub fn set_ns(&mut self, value: bool) {
549        let data = self.buffer.as_mut();
550        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
551        let raw = if value {
552            raw | field::FLG_NS
553        } else {
554            raw & !field::FLG_NS
555        };
556        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
557    }
558
559    /// Set the header length, in octets.
560    #[inline]
561    pub fn set_header_len(&mut self, value: u8) {
562        let data = self.buffer.as_mut();
563        let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
564        let raw = (raw & !0xf000) | ((value as u16) / 4) << 12;
565        NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
566    }
567
568    /// Set the window size field.
569    #[inline]
570    pub fn set_window_len(&mut self, value: u16) {
571        let data = self.buffer.as_mut();
572        NetworkEndian::write_u16(&mut data[field::WIN_SIZE], value)
573    }
574
575    /// Set the checksum field.
576    #[inline]
577    pub fn set_checksum(&mut self, value: u16) {
578        let data = self.buffer.as_mut();
579        NetworkEndian::write_u16(&mut data[field::CHECKSUM], value)
580    }
581
582    /// Set the urgent pointer field.
583    #[inline]
584    pub fn set_urgent_at(&mut self, value: u16) {
585        let data = self.buffer.as_mut();
586        NetworkEndian::write_u16(&mut data[field::URGENT], value)
587    }
588
589    /// Compute and fill in the header checksum.
590    ///
591    /// # Panics
592    /// This function panics unless `src_addr` and `dst_addr` belong to the same family,
593    /// and that family is IPv4 or IPv6.
594    pub fn fill_checksum(&mut self, src_addr: &IpAddress, dst_addr: &IpAddress) {
595        self.set_checksum(0);
596        let checksum = {
597            let data = self.buffer.as_ref();
598            !checksum::combine(&[
599                checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp, data.len() as u32),
600                checksum::data(data),
601            ])
602        };
603        self.set_checksum(checksum)
604    }
605
606    /// Return a pointer to the options.
607    #[inline]
608    pub fn options_mut(&mut self) -> &mut [u8] {
609        let header_len = self.header_len();
610        let data = self.buffer.as_mut();
611        &mut data[field::OPTIONS(header_len)]
612    }
613
614    /// Return a mutable pointer to the payload data.
615    #[inline]
616    pub fn payload_mut(&mut self) -> &mut [u8] {
617        let header_len = self.header_len() as usize;
618        let data = self.buffer.as_mut();
619        &mut data[header_len..]
620    }
621}
622
623impl<T: AsRef<[u8]>> AsRef<[u8]> for Packet<T> {
624    fn as_ref(&self) -> &[u8] {
625        self.buffer.as_ref()
626    }
627}
628
629/// A representation of a single TCP option.
630#[derive(Debug, PartialEq, Eq, Clone, Copy)]
631#[cfg_attr(feature = "defmt", derive(defmt::Format))]
632pub enum TcpOption<'a> {
633    EndOfList,
634    NoOperation,
635    MaxSegmentSize(u16),
636    WindowScale(u8),
637    SackPermitted,
638    SackRange([Option<(u32, u32)>; 3]),
639    TimeStamp { tsval: u32, tsecr: u32 },
640    Unknown { kind: u8, data: &'a [u8] },
641}
642
643impl<'a> TcpOption<'a> {
644    pub fn parse(buffer: &'a [u8]) -> Result<(&'a [u8], TcpOption<'a>)> {
645        let (length, option);
646        match *buffer.first().ok_or(Error)? {
647            field::OPT_END => {
648                length = 1;
649                option = TcpOption::EndOfList;
650            }
651            field::OPT_NOP => {
652                length = 1;
653                option = TcpOption::NoOperation;
654            }
655            kind => {
656                length = *buffer.get(1).ok_or(Error)? as usize;
657                let data = buffer.get(2..length).ok_or(Error)?;
658                match (kind, length) {
659                    (field::OPT_END, _) | (field::OPT_NOP, _) => unreachable!(),
660                    (field::OPT_MSS, 4) => {
661                        option = TcpOption::MaxSegmentSize(NetworkEndian::read_u16(data))
662                    }
663                    (field::OPT_MSS, _) => return Err(Error),
664                    (field::OPT_WS, 3) => option = TcpOption::WindowScale(data[0]),
665                    (field::OPT_WS, _) => return Err(Error),
666                    (field::OPT_SACKPERM, 2) => option = TcpOption::SackPermitted,
667                    (field::OPT_SACKPERM, _) => return Err(Error),
668                    (field::OPT_SACKRNG, n) => {
669                        if n < 10 || (n - 2) % 8 != 0 {
670                            return Err(Error);
671                        }
672                        if n > 26 {
673                            // It's possible for a remote to send 4 SACK blocks, but extremely rare.
674                            // Better to "lose" that 4th block and save the extra RAM and CPU
675                            // cycles in the vastly more common case.
676                            //
677                            // RFC 2018: SACK option that specifies n blocks will have a length of
678                            // 8*n+2 bytes, so the 40 bytes available for TCP options can specify a
679                            // maximum of 4 blocks.  It is expected that SACK will often be used in
680                            // conjunction with the Timestamp option used for RTTM [...] thus a
681                            // maximum of 3 SACK blocks will be allowed in this case.
682                            net_debug!("sACK with >3 blocks, truncating to 3");
683                        }
684                        let mut sack_ranges: [Option<(u32, u32)>; 3] = [None; 3];
685
686                        // RFC 2018: Each contiguous block of data queued at the data receiver is
687                        // defined in the SACK option by two 32-bit unsigned integers in network
688                        // byte order[...]
689                        sack_ranges.iter_mut().enumerate().for_each(|(i, nmut)| {
690                            let left = i * 8;
691                            *nmut = if left < data.len() {
692                                let mid = left + 4;
693                                let right = mid + 4;
694                                let range_left = NetworkEndian::read_u32(&data[left..mid]);
695                                let range_right = NetworkEndian::read_u32(&data[mid..right]);
696                                Some((range_left, range_right))
697                            } else {
698                                None
699                            };
700                        });
701                        option = TcpOption::SackRange(sack_ranges);
702                    }
703                    (field::OPT_TSTAMP, 10) => {
704                        let tsval = NetworkEndian::read_u32(&data[0..4]);
705                        let tsecr = NetworkEndian::read_u32(&data[4..8]);
706                        option = TcpOption::TimeStamp { tsval, tsecr };
707                    }
708                    (_, _) => option = TcpOption::Unknown { kind, data },
709                }
710            }
711        }
712        Ok((&buffer[length..], option))
713    }
714
715    pub fn buffer_len(&self) -> usize {
716        match *self {
717            TcpOption::EndOfList => 1,
718            TcpOption::NoOperation => 1,
719            TcpOption::MaxSegmentSize(_) => 4,
720            TcpOption::WindowScale(_) => 3,
721            TcpOption::SackPermitted => 2,
722            TcpOption::SackRange(s) => s.iter().filter(|s| s.is_some()).count() * 8 + 2,
723            TcpOption::TimeStamp { tsval: _, tsecr: _ } => 10,
724            TcpOption::Unknown { data, .. } => 2 + data.len(),
725        }
726    }
727
728    pub fn emit<'b>(&self, buffer: &'b mut [u8]) -> &'b mut [u8] {
729        let length;
730        match *self {
731            TcpOption::EndOfList => {
732                length = 1;
733                // There may be padding space which also should be initialized.
734                for p in buffer.iter_mut() {
735                    *p = field::OPT_END;
736                }
737            }
738            TcpOption::NoOperation => {
739                length = 1;
740                buffer[0] = field::OPT_NOP;
741            }
742            _ => {
743                length = self.buffer_len();
744                buffer[1] = length as u8;
745                match self {
746                    &TcpOption::EndOfList | &TcpOption::NoOperation => unreachable!(),
747                    &TcpOption::MaxSegmentSize(value) => {
748                        buffer[0] = field::OPT_MSS;
749                        NetworkEndian::write_u16(&mut buffer[2..], value)
750                    }
751                    &TcpOption::WindowScale(value) => {
752                        buffer[0] = field::OPT_WS;
753                        buffer[2] = value;
754                    }
755                    &TcpOption::SackPermitted => {
756                        buffer[0] = field::OPT_SACKPERM;
757                    }
758                    &TcpOption::SackRange(slice) => {
759                        buffer[0] = field::OPT_SACKRNG;
760                        slice
761                            .iter()
762                            .filter(|s| s.is_some())
763                            .enumerate()
764                            .for_each(|(i, s)| {
765                                let (first, second) = *s.as_ref().unwrap();
766                                let pos = i * 8 + 2;
767                                NetworkEndian::write_u32(&mut buffer[pos..], first);
768                                NetworkEndian::write_u32(&mut buffer[pos + 4..], second);
769                            });
770                    }
771                    &TcpOption::TimeStamp { tsval, tsecr } => {
772                        buffer[0] = field::OPT_TSTAMP;
773                        NetworkEndian::write_u32(&mut buffer[2..], tsval);
774                        NetworkEndian::write_u32(&mut buffer[6..], tsecr);
775                    }
776                    &TcpOption::Unknown {
777                        kind,
778                        data: provided,
779                    } => {
780                        buffer[0] = kind;
781                        buffer[2..].copy_from_slice(provided)
782                    }
783                }
784            }
785        }
786        &mut buffer[length..]
787    }
788}
789
790/// The possible control flags of a Transmission Control Protocol packet.
791#[derive(Debug, PartialEq, Eq, Clone, Copy)]
792#[cfg_attr(feature = "defmt", derive(defmt::Format))]
793pub enum Control {
794    None,
795    Psh,
796    Syn,
797    Fin,
798    Rst,
799}
800
801#[allow(clippy::len_without_is_empty)]
802impl Control {
803    /// Return the length of a control flag, in terms of sequence space.
804    pub const fn len(self) -> usize {
805        match self {
806            Control::Syn | Control::Fin => 1,
807            _ => 0,
808        }
809    }
810
811    /// Turn the PSH flag into no flag, and keep the rest as-is.
812    pub const fn quash_psh(self) -> Control {
813        match self {
814            Control::Psh => Control::None,
815            _ => self,
816        }
817    }
818}
819
820/// A high-level representation of a Transmission Control Protocol packet.
821#[derive(Debug, PartialEq, Eq, Clone, Copy)]
822pub struct Repr<'a> {
823    pub src_port: u16,
824    pub dst_port: u16,
825    pub control: Control,
826    pub seq_number: SeqNumber,
827    pub ack_number: Option<SeqNumber>,
828    pub window_len: u16,
829    pub window_scale: Option<u8>,
830    pub max_seg_size: Option<u16>,
831    pub sack_permitted: bool,
832    pub sack_ranges: [Option<(u32, u32)>; 3],
833    pub timestamp: Option<TcpTimestampRepr>,
834    pub payload: &'a [u8],
835}
836
837pub type TcpTimestampGenerator = fn() -> u32;
838
839#[derive(Debug, PartialEq, Eq, Clone, Copy)]
840pub struct TcpTimestampRepr {
841    pub tsval: u32,
842    pub tsecr: u32,
843}
844
845impl TcpTimestampRepr {
846    pub fn new(tsval: u32, tsecr: u32) -> Self {
847        Self { tsval, tsecr }
848    }
849
850    pub fn generate_reply(&self, generator: Option<TcpTimestampGenerator>) -> Option<Self> {
851        Self::generate_reply_with_tsval(generator, self.tsval)
852    }
853
854    pub fn generate_reply_with_tsval(
855        generator: Option<TcpTimestampGenerator>,
856        tsval: u32,
857    ) -> Option<Self> {
858        Some(Self::new(generator?(), tsval))
859    }
860}
861
862impl<'a> Repr<'a> {
863    /// Parse a Transmission Control Protocol packet and return a high-level representation.
864    pub fn parse<T>(
865        packet: &Packet<&'a T>,
866        src_addr: &IpAddress,
867        dst_addr: &IpAddress,
868        checksum_caps: &ChecksumCapabilities,
869    ) -> Result<Repr<'a>>
870    where
871        T: AsRef<[u8]> + ?Sized,
872    {
873        packet.check_len()?;
874
875        // Source and destination ports must be present.
876        if packet.src_port() == 0 {
877            return Err(Error);
878        }
879        if packet.dst_port() == 0 {
880            return Err(Error);
881        }
882        // Valid checksum is expected.
883        if checksum_caps.tcp.rx() && !packet.verify_checksum(src_addr, dst_addr) {
884            return Err(Error);
885        }
886
887        let control = match (packet.syn(), packet.fin(), packet.rst(), packet.psh()) {
888            (false, false, false, false) => Control::None,
889            (false, false, false, true) => Control::Psh,
890            (true, false, false, _) => Control::Syn,
891            (false, true, false, _) => Control::Fin,
892            (false, false, true, _) => Control::Rst,
893            _ => return Err(Error),
894        };
895        let ack_number = match packet.ack() {
896            true => Some(packet.ack_number()),
897            false => None,
898        };
899        // The PSH flag is ignored.
900        // The URG flag and the urgent field is ignored. This behavior is standards-compliant,
901        // however, most deployed systems (e.g. Linux) are *not* standards-compliant, and would
902        // cut the byte at the urgent pointer from the stream.
903
904        let mut max_seg_size = None;
905        let mut window_scale = None;
906        let mut options = packet.options();
907        let mut sack_permitted = false;
908        let mut sack_ranges = [None, None, None];
909        let mut timestamp = None;
910        while !options.is_empty() {
911            let (next_options, option) = TcpOption::parse(options)?;
912            match option {
913                TcpOption::EndOfList => break,
914                TcpOption::NoOperation => (),
915                TcpOption::MaxSegmentSize(value) => max_seg_size = Some(value),
916                TcpOption::WindowScale(value) => {
917                    // RFC 1323: Thus, the shift count must be limited to 14 (which allows windows
918                    // of 2**30 = 1 Gigabyte). If a Window Scale option is received with a shift.cnt
919                    // value exceeding 14, the TCP should log the error but use 14 instead of the
920                    // specified value.
921                    window_scale = if value > 14 {
922                        net_debug!(
923                            "{}:{}:{}:{}: parsed window scaling factor >14, setting to 14",
924                            src_addr,
925                            packet.src_port(),
926                            dst_addr,
927                            packet.dst_port()
928                        );
929                        Some(14)
930                    } else {
931                        Some(value)
932                    };
933                }
934                TcpOption::SackPermitted => sack_permitted = true,
935                TcpOption::SackRange(slice) => sack_ranges = slice,
936                TcpOption::TimeStamp { tsval, tsecr } => {
937                    timestamp = Some(TcpTimestampRepr::new(tsval, tsecr));
938                }
939                _ => (),
940            }
941            options = next_options;
942        }
943
944        Ok(Repr {
945            src_port: packet.src_port(),
946            dst_port: packet.dst_port(),
947            control: control,
948            seq_number: packet.seq_number(),
949            ack_number: ack_number,
950            window_len: packet.window_len(),
951            window_scale: window_scale,
952            max_seg_size: max_seg_size,
953            sack_permitted: sack_permitted,
954            sack_ranges: sack_ranges,
955            timestamp: timestamp,
956            payload: packet.payload(),
957        })
958    }
959
960    /// Return the length of a header that will be emitted from this high-level representation.
961    ///
962    /// This should be used for buffer space calculations.
963    /// The TCP header length is a multiple of 4.
964    pub fn header_len(&self) -> usize {
965        let mut length = field::URGENT.end;
966        if self.max_seg_size.is_some() {
967            length += 4
968        }
969        if self.window_scale.is_some() {
970            length += 3
971        }
972        if self.sack_permitted {
973            length += 2;
974        }
975        if self.timestamp.is_some() {
976            length += 10;
977        }
978        let sack_range_len: usize = self
979            .sack_ranges
980            .iter()
981            .map(|o| o.map(|_| 8).unwrap_or(0))
982            .sum();
983        if sack_range_len > 0 {
984            length += sack_range_len + 2;
985        }
986        if !length.is_multiple_of(4) {
987            length += 4 - length % 4;
988        }
989        length
990    }
991
992    /// Return the length of a packet that will be emitted from this high-level representation.
993    pub fn buffer_len(&self) -> usize {
994        self.header_len() + self.payload.len()
995    }
996
997    /// Emit a high-level representation into a Transmission Control Protocol packet.
998    pub fn emit<T>(
999        &self,
1000        packet: &mut Packet<&mut T>,
1001        src_addr: &IpAddress,
1002        dst_addr: &IpAddress,
1003        checksum_caps: &ChecksumCapabilities,
1004    ) where
1005        T: AsRef<[u8]> + AsMut<[u8]> + ?Sized,
1006    {
1007        packet.set_src_port(self.src_port);
1008        packet.set_dst_port(self.dst_port);
1009        packet.set_seq_number(self.seq_number);
1010        packet.set_ack_number(self.ack_number.unwrap_or(SeqNumber(0)));
1011        packet.set_window_len(self.window_len);
1012        packet.set_header_len(self.header_len() as u8);
1013        packet.clear_flags();
1014        match self.control {
1015            Control::None => (),
1016            Control::Psh => packet.set_psh(true),
1017            Control::Syn => packet.set_syn(true),
1018            Control::Fin => packet.set_fin(true),
1019            Control::Rst => packet.set_rst(true),
1020        }
1021        packet.set_ack(self.ack_number.is_some());
1022        {
1023            let mut options = packet.options_mut();
1024            if let Some(value) = self.max_seg_size {
1025                let tmp = options;
1026                options = TcpOption::MaxSegmentSize(value).emit(tmp);
1027            }
1028            if let Some(value) = self.window_scale {
1029                let tmp = options;
1030                options = TcpOption::WindowScale(value).emit(tmp);
1031            }
1032            if self.sack_permitted {
1033                let tmp = options;
1034                options = TcpOption::SackPermitted.emit(tmp);
1035            } else if self.ack_number.is_some() && self.sack_ranges.iter().any(|s| s.is_some()) {
1036                let tmp = options;
1037                options = TcpOption::SackRange(self.sack_ranges).emit(tmp);
1038            }
1039            if let Some(timestamp) = self.timestamp {
1040                let tmp = options;
1041                options = TcpOption::TimeStamp {
1042                    tsval: timestamp.tsval,
1043                    tsecr: timestamp.tsecr,
1044                }
1045                .emit(tmp);
1046            }
1047
1048            if !options.is_empty() {
1049                TcpOption::EndOfList.emit(options);
1050            }
1051        }
1052        packet.set_urgent_at(0);
1053        packet.payload_mut()[..self.payload.len()].copy_from_slice(self.payload);
1054
1055        if checksum_caps.tcp.tx() {
1056            packet.fill_checksum(src_addr, dst_addr)
1057        } else {
1058            // make sure we get a consistently zeroed checksum,
1059            // since implementations might rely on it
1060            packet.set_checksum(0);
1061        }
1062    }
1063
1064    /// Return the length of the segment, in terms of sequence space.
1065    pub const fn segment_len(&self) -> usize {
1066        self.payload.len() + self.control.len()
1067    }
1068
1069    /// Return whether the segment has no flags set (except PSH) and no data.
1070    pub const fn is_empty(&self) -> bool {
1071        match self.control {
1072            _ if !self.payload.is_empty() => false,
1073            Control::Syn | Control::Fin | Control::Rst => false,
1074            Control::None | Control::Psh => true,
1075        }
1076    }
1077}
1078
1079impl<T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&T> {
1080    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1081        // Cannot use Repr::parse because we don't have the IP addresses.
1082        write!(f, "TCP src={} dst={}", self.src_port(), self.dst_port())?;
1083        if self.syn() {
1084            write!(f, " syn")?
1085        }
1086        if self.fin() {
1087            write!(f, " fin")?
1088        }
1089        if self.rst() {
1090            write!(f, " rst")?
1091        }
1092        if self.psh() {
1093            write!(f, " psh")?
1094        }
1095        if self.ece() {
1096            write!(f, " ece")?
1097        }
1098        if self.cwr() {
1099            write!(f, " cwr")?
1100        }
1101        if self.ns() {
1102            write!(f, " ns")?
1103        }
1104        write!(f, " seq={}", self.seq_number())?;
1105        if self.ack() {
1106            write!(f, " ack={}", self.ack_number())?;
1107        }
1108        write!(f, " win={}", self.window_len())?;
1109        if self.urg() {
1110            write!(f, " urg={}", self.urgent_at())?;
1111        }
1112        write!(f, " len={}", self.payload().len())?;
1113
1114        let mut options = self.options();
1115        while !options.is_empty() {
1116            let (next_options, option) = match TcpOption::parse(options) {
1117                Ok(res) => res,
1118                Err(err) => return write!(f, " ({err})"),
1119            };
1120            match option {
1121                TcpOption::EndOfList => break,
1122                TcpOption::NoOperation => (),
1123                TcpOption::MaxSegmentSize(value) => write!(f, " mss={value}")?,
1124                TcpOption::WindowScale(value) => write!(f, " ws={value}")?,
1125                TcpOption::SackPermitted => write!(f, " sACK")?,
1126                TcpOption::SackRange(slice) => write!(f, " sACKr{slice:?}")?, // debug print conveniently includes the []s
1127                TcpOption::TimeStamp { tsval, tsecr } => {
1128                    write!(f, " tsval {tsval:08x} tsecr {tsecr:08x}")?
1129                }
1130                TcpOption::Unknown { kind, .. } => write!(f, " opt({kind})")?,
1131            }
1132            options = next_options;
1133        }
1134        Ok(())
1135    }
1136}
1137
1138impl<'a> fmt::Display for Repr<'a> {
1139    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1140        write!(f, "TCP src={} dst={}", self.src_port, self.dst_port)?;
1141        match self.control {
1142            Control::Syn => write!(f, " syn")?,
1143            Control::Fin => write!(f, " fin")?,
1144            Control::Rst => write!(f, " rst")?,
1145            Control::Psh => write!(f, " psh")?,
1146            Control::None => (),
1147        }
1148        write!(f, " seq={}", self.seq_number)?;
1149        if let Some(ack_number) = self.ack_number {
1150            write!(f, " ack={ack_number}")?;
1151        }
1152        write!(f, " win={}", self.window_len)?;
1153        write!(f, " len={}", self.payload.len())?;
1154        if let Some(max_seg_size) = self.max_seg_size {
1155            write!(f, " mss={max_seg_size}")?;
1156        }
1157        Ok(())
1158    }
1159}
1160
1161#[cfg(feature = "defmt")]
1162impl<'a> defmt::Format for Repr<'a> {
1163    fn format(&self, fmt: defmt::Formatter) {
1164        defmt::write!(fmt, "TCP src={} dst={}", self.src_port, self.dst_port);
1165        match self.control {
1166            Control::Syn => defmt::write!(fmt, " syn"),
1167            Control::Fin => defmt::write!(fmt, " fin"),
1168            Control::Rst => defmt::write!(fmt, " rst"),
1169            Control::Psh => defmt::write!(fmt, " psh"),
1170            Control::None => (),
1171        }
1172        defmt::write!(fmt, " seq={}", self.seq_number);
1173        if let Some(ack_number) = self.ack_number {
1174            defmt::write!(fmt, " ack={}", ack_number);
1175        }
1176        defmt::write!(fmt, " win={}", self.window_len);
1177        defmt::write!(fmt, " len={}", self.payload.len());
1178        if let Some(max_seg_size) = self.max_seg_size {
1179            defmt::write!(fmt, " mss={}", max_seg_size);
1180        }
1181    }
1182}
1183
1184use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
1185
1186impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
1187    fn pretty_print(
1188        buffer: &dyn AsRef<[u8]>,
1189        f: &mut fmt::Formatter,
1190        indent: &mut PrettyIndent,
1191    ) -> fmt::Result {
1192        match Packet::new_checked(buffer) {
1193            Err(err) => write!(f, "{indent}({err})"),
1194            Ok(packet) => write!(f, "{indent}{packet}"),
1195        }
1196    }
1197}
1198
1199#[cfg(test)]
1200mod test {
1201    use super::*;
1202    #[cfg(feature = "proto-ipv4")]
1203    use crate::wire::Ipv4Address;
1204
1205    #[cfg(feature = "proto-ipv4")]
1206    const SRC_ADDR: Ipv4Address = Ipv4Address::new(192, 168, 1, 1);
1207    #[cfg(feature = "proto-ipv4")]
1208    const DST_ADDR: Ipv4Address = Ipv4Address::new(192, 168, 1, 2);
1209
1210    #[cfg(feature = "proto-ipv4")]
1211    static PACKET_BYTES: [u8; 28] = [
1212        0xbf, 0x00, 0x00, 0x50, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x60, 0x35, 0x01,
1213        0x23, 0x01, 0xb6, 0x02, 0x01, 0x03, 0x03, 0x0c, 0x01, 0xaa, 0x00, 0x00, 0xff,
1214    ];
1215
1216    #[cfg(feature = "proto-ipv4")]
1217    static OPTION_BYTES: [u8; 4] = [0x03, 0x03, 0x0c, 0x01];
1218
1219    #[cfg(feature = "proto-ipv4")]
1220    static PAYLOAD_BYTES: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
1221
1222    #[test]
1223    #[cfg(feature = "proto-ipv4")]
1224    fn test_deconstruct() {
1225        let packet = Packet::new_unchecked(&PACKET_BYTES[..]);
1226        assert_eq!(packet.src_port(), 48896);
1227        assert_eq!(packet.dst_port(), 80);
1228        assert_eq!(packet.seq_number(), SeqNumber(0x01234567));
1229        assert_eq!(packet.ack_number(), SeqNumber(0x89abcdefu32 as i32));
1230        assert_eq!(packet.header_len(), 24);
1231        assert!(packet.fin());
1232        assert!(!packet.syn());
1233        assert!(packet.rst());
1234        assert!(!packet.psh());
1235        assert!(packet.ack());
1236        assert!(packet.urg());
1237        assert_eq!(packet.window_len(), 0x0123);
1238        assert_eq!(packet.urgent_at(), 0x0201);
1239        assert_eq!(packet.checksum(), 0x01b6);
1240        assert_eq!(packet.options(), &OPTION_BYTES[..]);
1241        assert_eq!(packet.payload(), &PAYLOAD_BYTES[..]);
1242        assert!(packet.verify_checksum(&SRC_ADDR.into(), &DST_ADDR.into()));
1243    }
1244
1245    #[test]
1246    #[cfg(feature = "proto-ipv4")]
1247    fn test_construct() {
1248        let mut bytes = vec![0xa5; PACKET_BYTES.len()];
1249        let mut packet = Packet::new_unchecked(&mut bytes);
1250        packet.set_src_port(48896);
1251        packet.set_dst_port(80);
1252        packet.set_seq_number(SeqNumber(0x01234567));
1253        packet.set_ack_number(SeqNumber(0x89abcdefu32 as i32));
1254        packet.set_header_len(24);
1255        packet.clear_flags();
1256        packet.set_fin(true);
1257        packet.set_syn(false);
1258        packet.set_rst(true);
1259        packet.set_psh(false);
1260        packet.set_ack(true);
1261        packet.set_urg(true);
1262        packet.set_window_len(0x0123);
1263        packet.set_urgent_at(0x0201);
1264        packet.set_checksum(0xEEEE);
1265        packet.options_mut().copy_from_slice(&OPTION_BYTES[..]);
1266        packet.payload_mut().copy_from_slice(&PAYLOAD_BYTES[..]);
1267        packet.fill_checksum(&SRC_ADDR.into(), &DST_ADDR.into());
1268        assert_eq!(&*packet.into_inner(), &PACKET_BYTES[..]);
1269    }
1270
1271    #[test]
1272    #[cfg(feature = "proto-ipv4")]
1273    fn test_truncated() {
1274        let packet = Packet::new_unchecked(&PACKET_BYTES[..23]);
1275        assert_eq!(packet.check_len(), Err(Error));
1276    }
1277
1278    #[test]
1279    fn test_impossible_len() {
1280        let mut bytes = vec![0; 20];
1281        let mut packet = Packet::new_unchecked(&mut bytes);
1282        packet.set_header_len(10);
1283        assert_eq!(packet.check_len(), Err(Error));
1284    }
1285
1286    #[cfg(feature = "proto-ipv4")]
1287    static SYN_PACKET_BYTES: [u8; 24] = [
1288        0xbf, 0x00, 0x00, 0x50, 0x01, 0x23, 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02, 0x01,
1289        0x23, 0x7a, 0x8d, 0x00, 0x00, 0xaa, 0x00, 0x00, 0xff,
1290    ];
1291
1292    #[cfg(feature = "proto-ipv4")]
1293    fn packet_repr() -> Repr<'static> {
1294        Repr {
1295            src_port: 48896,
1296            dst_port: 80,
1297            seq_number: SeqNumber(0x01234567),
1298            ack_number: None,
1299            window_len: 0x0123,
1300            window_scale: None,
1301            control: Control::Syn,
1302            max_seg_size: None,
1303            sack_permitted: false,
1304            sack_ranges: [None, None, None],
1305            timestamp: None,
1306            payload: &PAYLOAD_BYTES,
1307        }
1308    }
1309
1310    #[test]
1311    #[cfg(feature = "proto-ipv4")]
1312    fn test_parse() {
1313        let packet = Packet::new_unchecked(&SYN_PACKET_BYTES[..]);
1314        let repr = Repr::parse(
1315            &packet,
1316            &SRC_ADDR.into(),
1317            &DST_ADDR.into(),
1318            &ChecksumCapabilities::default(),
1319        )
1320        .unwrap();
1321        assert_eq!(repr, packet_repr());
1322    }
1323
1324    #[test]
1325    #[cfg(feature = "proto-ipv4")]
1326    fn test_emit() {
1327        let repr = packet_repr();
1328        let mut bytes = vec![0xa5; repr.buffer_len()];
1329        let mut packet = Packet::new_unchecked(&mut bytes);
1330        repr.emit(
1331            &mut packet,
1332            &SRC_ADDR.into(),
1333            &DST_ADDR.into(),
1334            &ChecksumCapabilities::default(),
1335        );
1336        assert_eq!(&*packet.into_inner(), &SYN_PACKET_BYTES[..]);
1337    }
1338
1339    #[test]
1340    #[cfg(feature = "proto-ipv4")]
1341    fn test_header_len_multiple_of_4() {
1342        let mut repr = packet_repr();
1343        repr.window_scale = Some(0); // This TCP Option needs 3 bytes.
1344        assert_eq!(repr.header_len() % 4, 0); // Should e.g. be 28 instead of 27.
1345    }
1346
1347    macro_rules! assert_option_parses {
1348        ($opt:expr, $data:expr) => {{
1349            assert_eq!(TcpOption::parse($data), Ok((&[][..], $opt)));
1350            let buffer = &mut [0; 40][..$opt.buffer_len()];
1351            assert_eq!($opt.emit(buffer), &mut []);
1352            assert_eq!(&*buffer, $data);
1353        }};
1354    }
1355
1356    #[test]
1357    fn test_tcp_options() {
1358        assert_option_parses!(TcpOption::EndOfList, &[0x00]);
1359        assert_option_parses!(TcpOption::NoOperation, &[0x01]);
1360        assert_option_parses!(TcpOption::MaxSegmentSize(1500), &[0x02, 0x04, 0x05, 0xdc]);
1361        assert_option_parses!(TcpOption::WindowScale(12), &[0x03, 0x03, 0x0c]);
1362        assert_option_parses!(TcpOption::SackPermitted, &[0x4, 0x02]);
1363        assert_option_parses!(
1364            TcpOption::SackRange([Some((500, 1500)), None, None]),
1365            &[0x05, 0x0a, 0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x05, 0xdc]
1366        );
1367        assert_option_parses!(
1368            TcpOption::SackRange([Some((875, 1225)), Some((1500, 2500)), None]),
1369            &[
1370                0x05, 0x12, 0x00, 0x00, 0x03, 0x6b, 0x00, 0x00, 0x04, 0xc9, 0x00, 0x00, 0x05, 0xdc,
1371                0x00, 0x00, 0x09, 0xc4
1372            ]
1373        );
1374        assert_option_parses!(
1375            TcpOption::SackRange([
1376                Some((875000, 1225000)),
1377                Some((1500000, 2500000)),
1378                Some((876543210, 876654320))
1379            ]),
1380            &[
1381                0x05, 0x1a, 0x00, 0x0d, 0x59, 0xf8, 0x00, 0x12, 0xb1, 0x28, 0x00, 0x16, 0xe3, 0x60,
1382                0x00, 0x26, 0x25, 0xa0, 0x34, 0x3e, 0xfc, 0xea, 0x34, 0x40, 0xae, 0xf0
1383            ]
1384        );
1385        assert_option_parses!(
1386            TcpOption::TimeStamp {
1387                tsval: 5000000,
1388                tsecr: 7000000
1389            },
1390            &[
1391                0x08, // data length
1392                0x0a, // type
1393                0x00, 0x4c, 0x4b, 0x40, //tsval
1394                0x00, 0x6a, 0xcf, 0xc0 //tsecr
1395            ]
1396        );
1397        assert_option_parses!(
1398            TcpOption::Unknown {
1399                kind: 12,
1400                data: &[1, 2, 3][..]
1401            },
1402            &[0x0c, 0x05, 0x01, 0x02, 0x03]
1403        )
1404    }
1405
1406    #[test]
1407    fn test_malformed_tcp_options() {
1408        assert_eq!(TcpOption::parse(&[]), Err(Error));
1409        assert_eq!(TcpOption::parse(&[0xc]), Err(Error));
1410        assert_eq!(TcpOption::parse(&[0xc, 0x05, 0x01, 0x02]), Err(Error));
1411        assert_eq!(TcpOption::parse(&[0xc, 0x01]), Err(Error));
1412        assert_eq!(TcpOption::parse(&[0x2, 0x02]), Err(Error));
1413        assert_eq!(TcpOption::parse(&[0x3, 0x02]), Err(Error));
1414    }
1415}