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#[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#[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 pub const fn new_unchecked(buffer: T) -> Packet<T> {
134 Packet { buffer }
135 }
136
137 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 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 pub fn into_inner(self) -> T {
171 self.buffer
172 }
173
174 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[inline]
291 pub fn checksum(&self) -> u16 {
292 let data = self.buffer.as_ref();
293 NetworkEndian::read_u16(&data[field::CHECKSUM])
294 }
295
296 #[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 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 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 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 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 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 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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 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 #[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 #[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#[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#[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 net_debug!("sACK with >3 blocks, truncating to 3");
717 }
718 let mut sack_ranges: [Option<(u32, u32)>; 3] = [None; 3];
719
720 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 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#[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 pub const fn len(self) -> usize {
839 match self {
840 Control::Syn | Control::Fin => 1,
841 _ => 0,
842 }
843 }
844
845 pub const fn quash_psh(self) -> Control {
847 match self {
848 Control::Psh => Control::None,
849 _ => self,
850 }
851 }
852}
853
854#[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 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 if packet.src_port() == 0 {
911 return Err(Error);
912 }
913 if packet.dst_port() == 0 {
914 return Err(Error);
915 }
916 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 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 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 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 pub fn buffer_len(&self) -> usize {
1028 self.header_len() + self.payload.len()
1029 }
1030
1031 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 packet.set_checksum(0);
1095 }
1096 }
1097
1098 pub const fn segment_len(&self) -> usize {
1100 self.payload.len() + self.control.len()
1101 }
1102
1103 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 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:?}")?, 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); assert_eq!(repr.header_len() % 4, 0); }
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, 0x0a, 0x00, 0x4c, 0x4b, 0x40, 0x00, 0x6a, 0xcf, 0xc0 ]
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 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}