1use crate::ip::IpNextProtocol;
4use crate::packet::Packet;
5
6use crate::util::{self, Octets};
7use std::net::Ipv6Addr;
8use std::net::{IpAddr, Ipv4Addr};
9
10use bytes::{Buf, BufMut, Bytes, BytesMut};
11use nex_core::bitfield::{u16be, u32be, u4};
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14
15pub const TCP_HEADER_LEN: usize = 20;
17pub const TCP_MIN_DATA_OFFSET: u8 = 5;
19pub const TCP_OPTION_MAX_LEN: usize = 40;
21pub const TCP_HEADER_MAX_LEN: usize = TCP_HEADER_LEN + TCP_OPTION_MAX_LEN;
23
24#[allow(non_camel_case_types)]
27#[repr(u8)]
28#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
29#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
30pub enum TcpOptionKind {
31 EOL = 0,
32 NOP = 1,
33 MSS = 2,
34 WSCALE = 3,
35 SACK_PERMITTED = 4,
36 SACK = 5,
37 ECHO = 6,
38 ECHO_REPLY = 7,
39 TIMESTAMPS = 8,
40 POCP = 9,
41 POSP = 10,
42 CC = 11,
43 CC_NEW = 12,
44 CC_ECHO = 13,
45 ALT_CHECKSUM_REQ = 14,
46 ALT_CHECKSUM_DATA = 15,
47 SKEETER = 16,
48 BUBBA = 17,
49 TRAILER_CHECKSUM = 18,
50 MD5_SIGNATURE = 19,
51 SCPS_CAPABILITIES = 20,
52 SELECTIVE_ACK = 21,
53 RECORD_BOUNDARIES = 22,
54 CORRUPTION_EXPERIENCED = 23,
55 SNAP = 24,
56 UNASSIGNED = 25,
57 TCP_COMPRESSION_FILTER = 26,
58 QUICK_START = 27,
59 USER_TIMEOUT = 28,
60 TCP_AO = 29,
61 MPTCP = 30,
62 RESERVED_31 = 31,
63 RESERVED_32 = 32,
64 RESERVED_33 = 33,
65 FAST_OPEN_COOKIE = 34,
66 TCP_ENO = 69,
67 ACC_ECNO_0 = 172,
68 ACC_ECNO_1 = 174,
69 EXPERIMENT_1 = 253,
70 EXPERIMENT_2 = 254,
71 RESERVED(u8),
72}
73
74impl TcpOptionKind {
75 pub fn new(n: u8) -> TcpOptionKind {
77 match n {
78 0 => TcpOptionKind::EOL,
79 1 => TcpOptionKind::NOP,
80 2 => TcpOptionKind::MSS,
81 3 => TcpOptionKind::WSCALE,
82 4 => TcpOptionKind::SACK_PERMITTED,
83 5 => TcpOptionKind::SACK,
84 6 => TcpOptionKind::ECHO,
85 7 => TcpOptionKind::ECHO_REPLY,
86 8 => TcpOptionKind::TIMESTAMPS,
87 9 => TcpOptionKind::POCP,
88 10 => TcpOptionKind::POSP,
89 11 => TcpOptionKind::CC,
90 12 => TcpOptionKind::CC_NEW,
91 13 => TcpOptionKind::CC_ECHO,
92 14 => TcpOptionKind::ALT_CHECKSUM_REQ,
93 15 => TcpOptionKind::ALT_CHECKSUM_DATA,
94 16 => TcpOptionKind::SKEETER,
95 17 => TcpOptionKind::BUBBA,
96 18 => TcpOptionKind::TRAILER_CHECKSUM,
97 19 => TcpOptionKind::MD5_SIGNATURE,
98 20 => TcpOptionKind::SCPS_CAPABILITIES,
99 21 => TcpOptionKind::SELECTIVE_ACK,
100 22 => TcpOptionKind::RECORD_BOUNDARIES,
101 23 => TcpOptionKind::CORRUPTION_EXPERIENCED,
102 24 => TcpOptionKind::SNAP,
103 25 => TcpOptionKind::UNASSIGNED,
104 26 => TcpOptionKind::TCP_COMPRESSION_FILTER,
105 27 => TcpOptionKind::QUICK_START,
106 28 => TcpOptionKind::USER_TIMEOUT,
107 29 => TcpOptionKind::TCP_AO,
108 30 => TcpOptionKind::MPTCP,
109 31 => TcpOptionKind::RESERVED_31,
110 32 => TcpOptionKind::RESERVED_32,
111 33 => TcpOptionKind::RESERVED_33,
112 34 => TcpOptionKind::FAST_OPEN_COOKIE,
113 69 => TcpOptionKind::TCP_ENO,
114 172 => TcpOptionKind::ACC_ECNO_0,
115 174 => TcpOptionKind::ACC_ECNO_1,
116 253 => TcpOptionKind::EXPERIMENT_1,
117 254 => TcpOptionKind::EXPERIMENT_2,
118 _ => TcpOptionKind::RESERVED(n),
119 }
120 }
121
122 pub fn name(&self) -> &'static str {
124 match *self {
125 TcpOptionKind::EOL => "EOL",
126 TcpOptionKind::NOP => "NOP",
127 TcpOptionKind::MSS => "MSS",
128 TcpOptionKind::WSCALE => "WSCALE",
129 TcpOptionKind::SACK_PERMITTED => "SACK_PERMITTED",
130 TcpOptionKind::SACK => "SACK",
131 TcpOptionKind::ECHO => "ECHO",
132 TcpOptionKind::ECHO_REPLY => "ECHO_REPLY",
133 TcpOptionKind::TIMESTAMPS => "TIMESTAMPS",
134 TcpOptionKind::POCP => "POCP",
135 TcpOptionKind::POSP => "POSP",
136 TcpOptionKind::CC => "CC",
137 TcpOptionKind::CC_NEW => "CC_NEW",
138 TcpOptionKind::CC_ECHO => "CC_ECHO",
139 TcpOptionKind::ALT_CHECKSUM_REQ => "ALT_CHECKSUM_REQ",
140 TcpOptionKind::ALT_CHECKSUM_DATA => "ALT_CHECKSUM_DATA",
141 TcpOptionKind::SKEETER => "SKEETER",
142 TcpOptionKind::BUBBA => "BUBBA",
143 TcpOptionKind::TRAILER_CHECKSUM => "TRAILER_CHECKSUM",
144 TcpOptionKind::MD5_SIGNATURE => "MD5_SIGNATURE",
145 TcpOptionKind::SCPS_CAPABILITIES => "SCPS_CAPABILITIES",
146 TcpOptionKind::SELECTIVE_ACK => "SELECTIVE_ACK",
147 TcpOptionKind::RECORD_BOUNDARIES => "RECORD_BOUNDARIES",
148 TcpOptionKind::CORRUPTION_EXPERIENCED => "CORRUPTION_EXPERIENCED",
149 TcpOptionKind::SNAP => "SNAP",
150 TcpOptionKind::UNASSIGNED => "UNASSIGNED",
151 TcpOptionKind::TCP_COMPRESSION_FILTER => "TCP_COMPRESSION_FILTER",
152 TcpOptionKind::QUICK_START => "QUICK_START",
153 TcpOptionKind::USER_TIMEOUT => "USER_TIMEOUT",
154 TcpOptionKind::TCP_AO => "TCP_AO",
155 TcpOptionKind::MPTCP => "MPTCP",
156 TcpOptionKind::RESERVED_31 => "RESERVED_31",
157 TcpOptionKind::RESERVED_32 => "RESERVED_32",
158 TcpOptionKind::RESERVED_33 => "RESERVED_33",
159 TcpOptionKind::FAST_OPEN_COOKIE => "FAST_OPEN_COOKIE",
160 TcpOptionKind::TCP_ENO => "TCP_ENO",
161 TcpOptionKind::ACC_ECNO_0 => "ACC_ECNO_0",
162 TcpOptionKind::ACC_ECNO_1 => "ACC_ECNO_1",
163 TcpOptionKind::EXPERIMENT_1 => "EXPERIMENT_1",
164 TcpOptionKind::EXPERIMENT_2 => "EXPERIMENT_2",
165 TcpOptionKind::RESERVED(_) => "RESERVED",
166 }
167 }
168 pub fn value(&self) -> u8 {
170 match *self {
171 TcpOptionKind::EOL => 0,
172 TcpOptionKind::NOP => 1,
173 TcpOptionKind::MSS => 2,
174 TcpOptionKind::WSCALE => 3,
175 TcpOptionKind::SACK_PERMITTED => 4,
176 TcpOptionKind::SACK => 5,
177 TcpOptionKind::ECHO => 6,
178 TcpOptionKind::ECHO_REPLY => 7,
179 TcpOptionKind::TIMESTAMPS => 8,
180 TcpOptionKind::POCP => 9,
181 TcpOptionKind::POSP => 10,
182 TcpOptionKind::CC => 11,
183 TcpOptionKind::CC_NEW => 12,
184 TcpOptionKind::CC_ECHO => 13,
185 TcpOptionKind::ALT_CHECKSUM_REQ => 14,
186 TcpOptionKind::ALT_CHECKSUM_DATA => 15,
187 TcpOptionKind::SKEETER => 16,
188 TcpOptionKind::BUBBA => 17,
189 TcpOptionKind::TRAILER_CHECKSUM => 18,
190 TcpOptionKind::MD5_SIGNATURE => 19,
191 TcpOptionKind::SCPS_CAPABILITIES => 20,
192 TcpOptionKind::SELECTIVE_ACK => 21,
193 TcpOptionKind::RECORD_BOUNDARIES => 22,
194 TcpOptionKind::CORRUPTION_EXPERIENCED => 23,
195 TcpOptionKind::SNAP => 24,
196 TcpOptionKind::UNASSIGNED => 25,
197 TcpOptionKind::TCP_COMPRESSION_FILTER => 26,
198 TcpOptionKind::QUICK_START => 27,
199 TcpOptionKind::USER_TIMEOUT => 28,
200 TcpOptionKind::TCP_AO => 29,
201 TcpOptionKind::MPTCP => 30,
202 TcpOptionKind::RESERVED_31 => 31,
203 TcpOptionKind::RESERVED_32 => 32,
204 TcpOptionKind::RESERVED_33 => 33,
205 TcpOptionKind::FAST_OPEN_COOKIE => 34,
206 TcpOptionKind::TCP_ENO => 69,
207 TcpOptionKind::ACC_ECNO_0 => 172,
208 TcpOptionKind::ACC_ECNO_1 => 174,
209 TcpOptionKind::EXPERIMENT_1 => 253,
210 TcpOptionKind::EXPERIMENT_2 => 254,
211 TcpOptionKind::RESERVED(n) => n,
212 }
213 }
214 pub fn size(&self) -> usize {
216 match *self {
217 TcpOptionKind::EOL => 1,
218 TcpOptionKind::NOP => 1,
219 TcpOptionKind::MSS => 4,
220 TcpOptionKind::WSCALE => 3,
221 TcpOptionKind::SACK_PERMITTED => 2,
222 TcpOptionKind::SACK => 10,
223 TcpOptionKind::ECHO => 6,
224 TcpOptionKind::ECHO_REPLY => 6,
225 TcpOptionKind::TIMESTAMPS => 10,
226 TcpOptionKind::POCP => 2,
227 TcpOptionKind::POSP => 3,
228 TcpOptionKind::ALT_CHECKSUM_REQ => 3,
229 TcpOptionKind::ALT_CHECKSUM_DATA => 12,
230 TcpOptionKind::TRAILER_CHECKSUM => 3,
231 TcpOptionKind::MD5_SIGNATURE => 18,
232 TcpOptionKind::QUICK_START => 8,
233 TcpOptionKind::USER_TIMEOUT => 4,
234 _ => 0,
235 }
236 }
237}
238
239#[allow(non_snake_case)]
242#[allow(non_upper_case_globals)]
243pub mod TcpFlags {
244 pub const CWR: u8 = 0b10000000;
248 pub const ECE: u8 = 0b01000000;
254 pub const URG: u8 = 0b00100000;
256 pub const ACK: u8 = 0b00010000;
259 pub const PSH: u8 = 0b00001000;
261 pub const RST: u8 = 0b00000100;
263 pub const SYN: u8 = 0b00000010;
266 pub const FIN: u8 = 0b00000001;
268}
269
270#[derive(Clone, Debug, PartialEq, Eq)]
272#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
273pub struct TcpOptionHeader {
274 pub kind: TcpOptionKind,
275 pub length: Option<u8>,
276 pub data: Bytes,
277}
278
279impl TcpOptionHeader {
280 pub fn get_timestamp(&self) -> (u32, u32) {
282 if self.kind == TcpOptionKind::TIMESTAMPS && self.data.len() >= 8 {
283 let mut my: [u8; 4] = [0; 4];
284 my.copy_from_slice(&self.data[0..4]);
285 let mut their: [u8; 4] = [0; 4];
286 their.copy_from_slice(&self.data[4..8]);
287 (u32::from_be_bytes(my), u32::from_be_bytes(their))
288 } else {
289 return (0, 0);
290 }
291 }
292 pub fn get_mss(&self) -> u16 {
294 if self.kind == TcpOptionKind::MSS && self.data.len() >= 2 {
295 let mut mss: [u8; 2] = [0; 2];
296 mss.copy_from_slice(&self.data[0..2]);
297 u16::from_be_bytes(mss)
298 } else {
299 0
300 }
301 }
302 pub fn get_wscale(&self) -> u8 {
304 if self.kind == TcpOptionKind::WSCALE && self.data.len() > 0 {
305 self.data[0]
306 } else {
307 0
308 }
309 }
310}
311
312#[derive(Clone, Debug, PartialEq, Eq)]
314#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
315pub struct TcpOptionPacket {
316 kind: TcpOptionKind,
317 length: Option<u8>,
318 data: Bytes,
319}
320
321impl TcpOptionPacket {
322 pub fn nop() -> Self {
324 TcpOptionPacket {
325 kind: TcpOptionKind::NOP,
326 length: None,
327 data: Bytes::new(),
328 }
329 }
330
331 pub fn timestamp(my: u32, their: u32) -> Self {
335 let mut data = BytesMut::new();
336 data.extend_from_slice(&my.octets()[..]);
337 data.extend_from_slice(&their.octets()[..]);
338
339 TcpOptionPacket {
340 kind: TcpOptionKind::TIMESTAMPS,
341 length: Some(10),
342 data: data.freeze(),
343 }
344 }
345
346 pub fn mss(val: u16) -> Self {
349 let mut data = BytesMut::new();
350 data.extend_from_slice(&val.octets()[..]);
351
352 TcpOptionPacket {
353 kind: TcpOptionKind::MSS,
354 length: Some(4),
355 data: data.freeze(),
356 }
357 }
358
359 pub fn wscale(val: u8) -> Self {
362 TcpOptionPacket {
363 kind: TcpOptionKind::WSCALE,
364 length: Some(3),
365 data: Bytes::from(vec![val]),
366 }
367 }
368
369 pub fn sack_perm() -> Self {
373 TcpOptionPacket {
374 kind: TcpOptionKind::SACK_PERMITTED,
375 length: Some(2),
376 data: Bytes::new(),
377 }
378 }
379
380 pub fn selective_ack(acks: &[u32]) -> Self {
385 let mut data = BytesMut::new();
386 for ack in acks {
387 data.extend_from_slice(&ack.octets()[..]);
388 }
389 TcpOptionPacket {
390 kind: TcpOptionKind::SACK,
391 length: Some(1 + 1 + data.len() as u8),
392 data: data.freeze(),
393 }
394 }
395 pub fn kind(&self) -> TcpOptionKind {
397 self.kind
398 }
399 pub fn length(&self) -> u8 {
401 if let Some(len) = self.length {
402 len
403 } else {
404 0
406 }
407 }
408 pub fn get_timestamp(&self) -> (u32, u32) {
410 if self.kind == TcpOptionKind::TIMESTAMPS && self.data.len() >= 8 {
411 let mut my: [u8; 4] = [0; 4];
412 my.copy_from_slice(&self.data[0..4]);
413 let mut their: [u8; 4] = [0; 4];
414 their.copy_from_slice(&self.data[4..8]);
415 (u32::from_be_bytes(my), u32::from_be_bytes(their))
416 } else {
417 return (0, 0);
418 }
419 }
420 pub fn get_mss(&self) -> u16 {
422 if self.kind == TcpOptionKind::MSS && self.data.len() >= 2 {
423 let mut mss: [u8; 2] = [0; 2];
424 mss.copy_from_slice(&self.data[0..2]);
425 u16::from_be_bytes(mss)
426 } else {
427 0
428 }
429 }
430 pub fn get_wscale(&self) -> u8 {
432 if self.kind == TcpOptionKind::WSCALE && self.data.len() > 0 {
433 self.data[0]
434 } else {
435 0
436 }
437 }
438}
439
440#[derive(Clone, Debug, PartialEq, Eq)]
442#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
443pub struct TcpHeader {
444 pub source: u16be,
445 pub destination: u16be,
446 pub sequence: u32be,
447 pub acknowledgement: u32be,
448 pub data_offset: u4,
449 pub reserved: u4,
450 pub flags: u8,
451 pub window: u16be,
452 pub checksum: u16be,
453 pub urgent_ptr: u16be,
454 pub options: Vec<TcpOptionPacket>,
455}
456
457#[derive(Clone, Debug, PartialEq, Eq)]
459pub struct TcpPacket {
460 pub header: TcpHeader,
461 pub payload: Bytes,
462}
463
464impl Packet for TcpPacket {
465 type Header = TcpHeader;
466
467 fn from_buf(mut bytes: &[u8]) -> Option<Self> {
468 if bytes.len() < TCP_HEADER_LEN {
469 return None;
470 }
471
472 let source = bytes.get_u16();
473 let destination = bytes.get_u16();
474 let sequence = bytes.get_u32();
475 let acknowledgement = bytes.get_u32();
476
477 let offset_reserved = bytes.get_u8();
478 let data_offset = offset_reserved >> 4;
479 let reserved = offset_reserved & 0x0F;
480
481 let flags = bytes.get_u8();
482 let window = bytes.get_u16();
483 let checksum = bytes.get_u16();
484 let urgent_ptr = bytes.get_u16();
485
486 let header_len = data_offset as usize * 4;
487 if header_len < TCP_HEADER_LEN || bytes.len() + 20 < header_len {
488 return None;
489 }
490
491 let mut options = Vec::new();
492 let options_len = header_len - TCP_HEADER_LEN;
493 let (mut options_bytes, rest) = bytes.split_at(options_len);
494 bytes = rest;
495
496 while options_bytes.has_remaining() {
497 let kind = TcpOptionKind::new(options_bytes.get_u8());
498 match kind {
499 TcpOptionKind::EOL => {
500 options.push(TcpOptionPacket {
501 kind,
502 length: None,
503 data: Bytes::new(),
504 });
505 break;
506 }
507 TcpOptionKind::NOP => {
508 options.push(TcpOptionPacket {
509 kind,
510 length: None,
511 data: Bytes::new(),
512 });
513 }
514 _ => {
515 if options_bytes.remaining() < 1 {
516 return None;
517 }
518 let len = options_bytes.get_u8();
519 if len < 2 || (len as usize) > options_bytes.remaining() + 2 {
520 return None;
521 }
522 let data_len = (len - 2) as usize;
523 let (data_slice, rest) = options_bytes.split_at(data_len);
524 options_bytes = rest;
525 options.push(TcpOptionPacket {
526 kind,
527 length: Some(len),
528 data: Bytes::copy_from_slice(data_slice),
529 });
530 }
531 }
532 }
533
534 Some(TcpPacket {
535 header: TcpHeader {
536 source,
537 destination,
538 sequence,
539 acknowledgement,
540 data_offset: u4::from_be(data_offset),
541 reserved: u4::from_be(reserved),
542 flags,
543 window,
544 checksum,
545 urgent_ptr,
546 options,
547 },
548 payload: Bytes::copy_from_slice(bytes),
549 })
550 }
551 fn from_bytes(mut bytes: Bytes) -> Option<Self> {
552 Self::from_buf(&mut bytes)
553 }
554
555 fn to_bytes(&self) -> Bytes {
556 let mut enc_opt_len = 0usize;
558 for opt in &self.header.options {
559 match opt.kind {
560 TcpOptionKind::EOL | TcpOptionKind::NOP => enc_opt_len += 1,
561 _ => {
562 let len = opt.length.unwrap_or(2) as usize;
564 enc_opt_len += len;
565 }
566 }
567 }
568 let padded_opt_len = (enc_opt_len + 3) & !3;
570 let header_len = TCP_HEADER_LEN + padded_opt_len;
571 let data_offset_words = (header_len / 4) as u8;
573
574 let mut bytes = BytesMut::with_capacity(header_len + self.payload.len());
576 bytes.put_u16(self.header.source);
577 bytes.put_u16(self.header.destination);
578 bytes.put_u32(self.header.sequence);
579 bytes.put_u32(self.header.acknowledgement);
580
581 let offset_reserved = (data_offset_words << 4) | (self.header.reserved.to_be() & 0x0F);
582 bytes.put_u8(offset_reserved);
583
584 bytes.put_u8(self.header.flags);
585 bytes.put_u16(self.header.window);
586 bytes.put_u16(self.header.checksum);
587 bytes.put_u16(self.header.urgent_ptr);
588
589 let before_opts = bytes.len();
591 for opt in &self.header.options {
592 bytes.put_u8(opt.kind.value());
593 if let Some(length) = opt.length {
594 bytes.put_u8(length);
595 bytes.extend_from_slice(&opt.data);
596 }
597 }
598 let written_opt = bytes.len() - before_opts;
600 let pad = padded_opt_len.saturating_sub(written_opt);
601 for _ in 0..pad {
602 bytes.put_u8(0);
603 }
604
605 bytes.extend_from_slice(&self.payload);
607
608 bytes.freeze()
609 }
610
611 fn header(&self) -> Bytes {
612 self.to_bytes().slice(..self.header_len())
613 }
614
615 fn payload(&self) -> Bytes {
616 self.payload.clone()
617 }
618
619 fn header_len(&self) -> usize {
620 let base = TCP_HEADER_LEN;
621 let mut opt_len = 0;
622
623 for opt in &self.header.options {
624 match opt.kind {
625 TcpOptionKind::EOL | TcpOptionKind::NOP => {
626 opt_len += 1; }
628 _ => {
629 if let Some(len) = opt.length {
631 opt_len += len as usize;
632 } else {
633 opt_len += 2;
635 }
636 }
637 }
638 }
639
640 let total = base + opt_len;
641 (total + 3) & !0x03
643 }
644
645 fn payload_len(&self) -> usize {
646 self.payload.len()
647 }
648
649 fn total_len(&self) -> usize {
650 self.header_len() + self.payload_len()
651 }
652
653 fn into_parts(self) -> (Self::Header, Bytes) {
654 (self.header, self.payload)
655 }
656}
657
658impl TcpPacket {
659 pub fn tcp_options_length(&self) -> usize {
660 if self.header.data_offset > 5 {
661 self.header.data_offset as usize * 4 - 20
662 } else {
663 0
664 }
665 }
666}
667
668pub fn checksum(packet: &TcpPacket, source: &IpAddr, destination: &IpAddr) -> u16 {
669 match (source, destination) {
670 (IpAddr::V4(src), IpAddr::V4(dst)) => ipv4_checksum(packet, src, dst),
671 (IpAddr::V6(src), IpAddr::V6(dst)) => ipv6_checksum(packet, src, dst),
672 _ => 0, }
674}
675
676pub fn ipv4_checksum(packet: &TcpPacket, source: &Ipv4Addr, destination: &Ipv4Addr) -> u16 {
678 ipv4_checksum_adv(packet, &[], source, destination)
679}
680
681pub fn ipv4_checksum_adv(
689 packet: &TcpPacket,
690 extra_data: &[u8],
691 source: &Ipv4Addr,
692 destination: &Ipv4Addr,
693) -> u16 {
694 util::ipv4_checksum(
695 &packet.to_bytes(),
696 8,
697 extra_data,
698 source,
699 destination,
700 IpNextProtocol::Tcp,
701 )
702}
703
704pub fn ipv6_checksum(packet: &TcpPacket, source: &Ipv6Addr, destination: &Ipv6Addr) -> u16 {
706 ipv6_checksum_adv(packet, &[], source, destination)
707}
708
709pub fn ipv6_checksum_adv(
717 packet: &TcpPacket,
718 extra_data: &[u8],
719 source: &Ipv6Addr,
720 destination: &Ipv6Addr,
721) -> u16 {
722 util::ipv6_checksum(
723 &packet.to_bytes(),
724 8,
725 extra_data,
726 source,
727 destination,
728 IpNextProtocol::Tcp,
729 )
730}
731
732#[cfg(test)]
733mod tests {
734 use super::*;
735
736 #[test]
737 fn test_basic_tcp_parse() {
738 let ref_packet = Bytes::from_static(&[
739 0xc1, 0x67, 0x23, 0x28, 0x90, 0x37, 0xd2, 0xb8, 0x94, 0x4b, 0xb2, 0x76, 0x80, 0x18, 0x0f, 0xaf, 0xc0, 0x31, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x2c, 0x57, 0xcd, 0xa5, 0x02, 0xa0, 0x41, 0x92, 0x74, 0x65, 0x73, 0x74, ]);
750 let packet = TcpPacket::from_bytes(ref_packet.clone()).unwrap();
751
752 assert_eq!(packet.header.source, 0xc167);
753 assert_eq!(packet.header.destination, 0x2328);
754 assert_eq!(packet.header.sequence, 0x9037d2b8);
755 assert_eq!(packet.header.acknowledgement, 0x944bb276);
756 assert_eq!(packet.header.data_offset, 8); assert_eq!(packet.header.reserved, 0);
758 assert_eq!(packet.header.flags, 0x18); assert_eq!(packet.header.window, 0x0faf);
760 assert_eq!(packet.header.checksum, 0xc031);
761 assert_eq!(packet.header.urgent_ptr, 0x0000);
762 assert_eq!(packet.header.options.len(), 3);
763 assert_eq!(packet.header.options[0].kind, TcpOptionKind::NOP);
764 assert_eq!(packet.header.options[1].kind, TcpOptionKind::NOP);
765 assert_eq!(packet.header.options[2].kind, TcpOptionKind::TIMESTAMPS);
766 assert_eq!(
767 packet.header.options[2].get_timestamp(),
768 (0x2c57cda5, 0x02a04192)
769 );
770 assert_eq!(packet.payload, Bytes::from_static(b"test"));
771 assert_eq!(packet.header_len(), 32); assert_eq!(packet.to_bytes(), ref_packet);
773 assert_eq!(packet.header().len(), 32); assert_eq!(packet.payload().len(), 4);
775 }
776
777 #[test]
778 fn test_basic_tcp_create() {
779 let options = vec![
780 TcpOptionPacket::nop(),
781 TcpOptionPacket::nop(),
782 TcpOptionPacket::timestamp(0x2c57cda5, 0x02a04192),
783 ];
784
785 let packet = TcpPacket {
786 header: TcpHeader {
787 source: 0xc167,
788 destination: 0x2328,
789 sequence: 0x9037d2b8,
790 acknowledgement: 0x944bb276,
791 data_offset: 8.into(), reserved: 0.into(),
793 flags: 0x18, window: 0x0faf,
795 checksum: 0xc031,
796 urgent_ptr: 0x0000,
797 options: options.clone(),
798 },
799 payload: Bytes::from_static(b"test"),
800 };
801
802 let bytes = packet.to_bytes();
803 let parsed = TcpPacket::from_bytes(bytes.clone()).expect("Failed to parse TCP packet");
804
805 assert_eq!(parsed, packet);
806 assert_eq!(parsed.to_bytes(), bytes);
807 assert_eq!(parsed.header.options.len(), 3);
808 assert_eq!(
809 parsed.header.options[2].get_timestamp(),
810 (0x2c57cda5, 0x02a04192)
811 );
812 }
813}