1use crate::ip::IpNextLevelProtocol;
4use crate::Packet;
5use crate::PrimitiveValues;
6
7use alloc::{vec, vec::Vec};
8
9use nex_macro::packet;
10use nex_macro_helper::types::*;
11
12use crate::util::{self, Octets};
13use std::net::Ipv4Addr;
14use std::net::Ipv6Addr;
15
16#[cfg(feature = "serde")]
17use serde::{Deserialize, Serialize};
18
19pub const TCP_HEADER_LEN: usize = MutableTcpPacket::minimum_packet_size();
21pub const TCP_MIN_DATA_OFFSET: u8 = 5;
23pub const TCP_OPTION_MAX_LEN: usize = 40;
25pub const TCP_HEADER_MAX_LEN: usize = TCP_HEADER_LEN + TCP_OPTION_MAX_LEN;
27
28#[derive(Clone, Debug, PartialEq, Eq)]
30#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
31pub struct TcpOptionHeader {
32 pub kind: TcpOptionKind,
33 pub length: Option<u8>,
34 pub data: Vec<u8>,
35}
36
37impl TcpOptionHeader {
38 pub fn get_timestamp(&self) -> (u32, u32) {
40 if self.kind == TcpOptionKind::TIMESTAMPS && self.data.len() >= 8 {
41 let mut my: [u8; 4] = [0; 4];
42 my.copy_from_slice(&self.data[0..4]);
43 let mut their: [u8; 4] = [0; 4];
44 their.copy_from_slice(&self.data[4..8]);
45 (u32::from_be_bytes(my), u32::from_be_bytes(their))
46 } else {
47 return (0, 0);
48 }
49 }
50 pub fn get_mss(&self) -> u16 {
52 if self.kind == TcpOptionKind::MSS && self.data.len() >= 2 {
53 let mut mss: [u8; 2] = [0; 2];
54 mss.copy_from_slice(&self.data[0..2]);
55 u16::from_be_bytes(mss)
56 } else {
57 0
58 }
59 }
60 pub fn get_wscale(&self) -> u8 {
62 if self.kind == TcpOptionKind::WSCALE && self.data.len() > 0 {
63 self.data[0]
64 } else {
65 0
66 }
67 }
68}
69
70#[derive(Clone, Debug, PartialEq, Eq)]
72#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
73pub struct TcpHeader {
74 pub source: u16be,
75 pub destination: u16be,
76 pub sequence: u32be,
77 pub acknowledgement: u32be,
78 pub data_offset: u4,
79 pub reserved: u4,
80 pub flags: u8,
81 pub window: u16be,
82 pub checksum: u16be,
83 pub urgent_ptr: u16be,
84 pub options: Vec<TcpOptionHeader>,
85}
86
87impl TcpHeader {
88 pub fn from_bytes(packet: &[u8]) -> Result<TcpHeader, String> {
90 if packet.len() < TCP_HEADER_LEN {
91 return Err("Packet is too small for TCP header".to_string());
92 }
93 match TcpPacket::new(packet) {
94 Some(tcp_packet) => Ok(TcpHeader {
95 source: tcp_packet.get_source(),
96 destination: tcp_packet.get_destination(),
97 sequence: tcp_packet.get_sequence(),
98 acknowledgement: tcp_packet.get_acknowledgement(),
99 data_offset: tcp_packet.get_data_offset(),
100 reserved: tcp_packet.get_reserved(),
101 flags: tcp_packet.get_flags(),
102 window: tcp_packet.get_window(),
103 checksum: tcp_packet.get_checksum(),
104 urgent_ptr: tcp_packet.get_urgent_ptr(),
105 options: tcp_packet
106 .get_options_iter()
107 .map(|opt| TcpOptionHeader {
108 kind: opt.get_kind(),
109 length: opt.get_length_raw().first().cloned(),
110 data: opt.payload().to_vec(),
111 })
112 .collect(),
113 }),
114 None => Err("Failed to parse TCP packet".to_string()),
115 }
116 }
117 pub(crate) fn from_packet(tcp_packet: &TcpPacket) -> TcpHeader {
119 TcpHeader {
120 source: tcp_packet.get_source(),
121 destination: tcp_packet.get_destination(),
122 sequence: tcp_packet.get_sequence(),
123 acknowledgement: tcp_packet.get_acknowledgement(),
124 data_offset: tcp_packet.get_data_offset(),
125 reserved: tcp_packet.get_reserved(),
126 flags: tcp_packet.get_flags(),
127 window: tcp_packet.get_window(),
128 checksum: tcp_packet.get_checksum(),
129 urgent_ptr: tcp_packet.get_urgent_ptr(),
130 options: tcp_packet
131 .get_options_iter()
132 .map(|opt| TcpOptionHeader {
133 kind: opt.get_kind(),
134 length: opt.get_length_raw().first().cloned(),
135 data: opt.payload().to_vec(),
136 })
137 .collect(),
138 }
139 }
140}
141
142#[allow(non_snake_case)]
145#[allow(non_upper_case_globals)]
146pub mod TcpFlags {
147 pub const CWR: u8 = 0b10000000;
151 pub const ECE: u8 = 0b01000000;
157 pub const URG: u8 = 0b00100000;
159 pub const ACK: u8 = 0b00010000;
162 pub const PSH: u8 = 0b00001000;
164 pub const RST: u8 = 0b00000100;
166 pub const SYN: u8 = 0b00000010;
169 pub const FIN: u8 = 0b00000001;
171}
172
173#[packet]
175pub struct Tcp {
176 pub source: u16be,
177 pub destination: u16be,
178 pub sequence: u32be,
179 pub acknowledgement: u32be,
180 pub data_offset: u4,
181 pub reserved: u4,
182 pub flags: u8,
183 pub window: u16be,
184 pub checksum: u16be,
185 pub urgent_ptr: u16be,
186 #[length_fn = "tcp_options_length"]
187 pub options: Vec<TcpOption>,
188 #[payload]
189 pub payload: Vec<u8>,
190}
191
192#[allow(non_camel_case_types)]
195#[repr(u8)]
196#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
197#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
198pub enum TcpOptionKind {
199 EOL = 0,
200 NOP = 1,
201 MSS = 2,
202 WSCALE = 3,
203 SACK_PERMITTED = 4,
204 SACK = 5,
205 ECHO = 6,
206 ECHO_REPLY = 7,
207 TIMESTAMPS = 8,
208 POCP = 9,
209 POSP = 10,
210 CC = 11,
211 CC_NEW = 12,
212 CC_ECHO = 13,
213 ALT_CHECKSUM_REQ = 14,
214 ALT_CHECKSUM_DATA = 15,
215 SKEETER = 16,
216 BUBBA = 17,
217 TRAILER_CHECKSUM = 18,
218 MD5_SIGNATURE = 19,
219 SCPS_CAPABILITIES = 20,
220 SELECTIVE_ACK = 21,
221 RECORD_BOUNDARIES = 22,
222 CORRUPTION_EXPERIENCED = 23,
223 SNAP = 24,
224 UNASSIGNED = 25,
225 TCP_COMPRESSION_FILTER = 26,
226 QUICK_START = 27,
227 USER_TIMEOUT = 28,
228 TCP_AO = 29,
229 MPTCP = 30,
230 RESERVED_31 = 31,
231 RESERVED_32 = 32,
232 RESERVED_33 = 33,
233 FAST_OPEN_COOKIE = 34,
234 TCP_ENO = 69,
235 ACC_ECNO_0 = 172,
236 ACC_ECNO_1 = 174,
237 EXPERIMENT_1 = 253,
238 EXPERIMENT_2 = 254,
239 RESERVED(u8),
240}
241
242impl TcpOptionKind {
243 pub fn new(n: u8) -> TcpOptionKind {
245 match n {
246 0 => TcpOptionKind::EOL,
247 1 => TcpOptionKind::NOP,
248 2 => TcpOptionKind::MSS,
249 3 => TcpOptionKind::WSCALE,
250 4 => TcpOptionKind::SACK_PERMITTED,
251 5 => TcpOptionKind::SACK,
252 6 => TcpOptionKind::ECHO,
253 7 => TcpOptionKind::ECHO_REPLY,
254 8 => TcpOptionKind::TIMESTAMPS,
255 9 => TcpOptionKind::POCP,
256 10 => TcpOptionKind::POSP,
257 11 => TcpOptionKind::CC,
258 12 => TcpOptionKind::CC_NEW,
259 13 => TcpOptionKind::CC_ECHO,
260 14 => TcpOptionKind::ALT_CHECKSUM_REQ,
261 15 => TcpOptionKind::ALT_CHECKSUM_DATA,
262 16 => TcpOptionKind::SKEETER,
263 17 => TcpOptionKind::BUBBA,
264 18 => TcpOptionKind::TRAILER_CHECKSUM,
265 19 => TcpOptionKind::MD5_SIGNATURE,
266 20 => TcpOptionKind::SCPS_CAPABILITIES,
267 21 => TcpOptionKind::SELECTIVE_ACK,
268 22 => TcpOptionKind::RECORD_BOUNDARIES,
269 23 => TcpOptionKind::CORRUPTION_EXPERIENCED,
270 24 => TcpOptionKind::SNAP,
271 25 => TcpOptionKind::UNASSIGNED,
272 26 => TcpOptionKind::TCP_COMPRESSION_FILTER,
273 27 => TcpOptionKind::QUICK_START,
274 28 => TcpOptionKind::USER_TIMEOUT,
275 29 => TcpOptionKind::TCP_AO,
276 30 => TcpOptionKind::MPTCP,
277 31 => TcpOptionKind::RESERVED_31,
278 32 => TcpOptionKind::RESERVED_32,
279 33 => TcpOptionKind::RESERVED_33,
280 34 => TcpOptionKind::FAST_OPEN_COOKIE,
281 69 => TcpOptionKind::TCP_ENO,
282 172 => TcpOptionKind::ACC_ECNO_0,
283 174 => TcpOptionKind::ACC_ECNO_1,
284 253 => TcpOptionKind::EXPERIMENT_1,
285 254 => TcpOptionKind::EXPERIMENT_2,
286 _ => TcpOptionKind::RESERVED(n),
287 }
288 }
289 pub fn name(&self) -> String {
291 match *self {
292 TcpOptionKind::EOL => String::from("EOL"),
293 TcpOptionKind::NOP => String::from("NOP"),
294 TcpOptionKind::MSS => String::from("MSS"),
295 TcpOptionKind::WSCALE => String::from("WSCALE"),
296 TcpOptionKind::SACK_PERMITTED => String::from("SACK_PERMITTED"),
297 TcpOptionKind::SACK => String::from("SACK"),
298 TcpOptionKind::ECHO => String::from("ECHO"),
299 TcpOptionKind::ECHO_REPLY => String::from("ECHO_REPLY"),
300 TcpOptionKind::TIMESTAMPS => String::from("TIMESTAMPS"),
301 TcpOptionKind::POCP => String::from("POCP"),
302 TcpOptionKind::POSP => String::from("POSP"),
303 TcpOptionKind::CC => String::from("CC"),
304 TcpOptionKind::CC_NEW => String::from("CC_NEW"),
305 TcpOptionKind::CC_ECHO => String::from("CC_ECHO"),
306 TcpOptionKind::ALT_CHECKSUM_REQ => String::from("ALT_CHECKSUM_REQ"),
307 TcpOptionKind::ALT_CHECKSUM_DATA => String::from("ALT_CHECKSUM_DATA"),
308 TcpOptionKind::SKEETER => String::from("SKEETER"),
309 TcpOptionKind::BUBBA => String::from("BUBBA"),
310 TcpOptionKind::TRAILER_CHECKSUM => String::from("TRAILER_CHECKSUM"),
311 TcpOptionKind::MD5_SIGNATURE => String::from("MD5_SIGNATURE"),
312 TcpOptionKind::SCPS_CAPABILITIES => String::from("SCPS_CAPABILITIES"),
313 TcpOptionKind::SELECTIVE_ACK => String::from("SELECTIVE_ACK"),
314 TcpOptionKind::RECORD_BOUNDARIES => String::from("RECORD_BOUNDARIES"),
315 TcpOptionKind::CORRUPTION_EXPERIENCED => String::from("CORRUPTION_EXPERIENCED"),
316 TcpOptionKind::SNAP => String::from("SNAP"),
317 TcpOptionKind::UNASSIGNED => String::from("UNASSIGNED"),
318 TcpOptionKind::TCP_COMPRESSION_FILTER => String::from("TCP_COMPRESSION_FILTER"),
319 TcpOptionKind::QUICK_START => String::from("QUICK_START"),
320 TcpOptionKind::USER_TIMEOUT => String::from("USER_TIMEOUT"),
321 TcpOptionKind::TCP_AO => String::from("TCP_AO"),
322 TcpOptionKind::MPTCP => String::from("MPTCP"),
323 TcpOptionKind::RESERVED_31 => String::from("RESERVED_31"),
324 TcpOptionKind::RESERVED_32 => String::from("RESERVED_32"),
325 TcpOptionKind::RESERVED_33 => String::from("RESERVED_33"),
326 TcpOptionKind::FAST_OPEN_COOKIE => String::from("FAST_OPEN_COOKIE"),
327 TcpOptionKind::TCP_ENO => String::from("TCP_ENO"),
328 TcpOptionKind::ACC_ECNO_0 => String::from("ACC_ECNO_0"),
329 TcpOptionKind::ACC_ECNO_1 => String::from("ACC_ECNO_1"),
330 TcpOptionKind::EXPERIMENT_1 => String::from("EXPERIMENT_1"),
331 TcpOptionKind::EXPERIMENT_2 => String::from("EXPERIMENT_2"),
332 TcpOptionKind::RESERVED(n) => format!("RESERVED_{}", n),
333 }
334 }
335 pub fn size(&self) -> usize {
337 match *self {
338 TcpOptionKind::EOL => 1,
339 TcpOptionKind::NOP => 1,
340 TcpOptionKind::MSS => 4,
341 TcpOptionKind::WSCALE => 3,
342 TcpOptionKind::SACK_PERMITTED => 2,
343 TcpOptionKind::SACK => 10,
344 TcpOptionKind::ECHO => 6,
345 TcpOptionKind::ECHO_REPLY => 6,
346 TcpOptionKind::TIMESTAMPS => 10,
347 TcpOptionKind::POCP => 2,
348 TcpOptionKind::POSP => 3,
349 TcpOptionKind::ALT_CHECKSUM_REQ => 3,
350 TcpOptionKind::ALT_CHECKSUM_DATA => 12,
351 TcpOptionKind::TRAILER_CHECKSUM => 3,
352 TcpOptionKind::MD5_SIGNATURE => 18,
353 TcpOptionKind::QUICK_START => 8,
354 TcpOptionKind::USER_TIMEOUT => 4,
355 _ => 0,
356 }
357 }
358}
359
360impl PrimitiveValues for TcpOptionKind {
361 type T = (u8,);
362 fn to_primitive_values(&self) -> (u8,) {
363 match *self {
364 TcpOptionKind::EOL => (0,),
365 TcpOptionKind::NOP => (1,),
366 TcpOptionKind::MSS => (2,),
367 TcpOptionKind::WSCALE => (3,),
368 TcpOptionKind::SACK_PERMITTED => (4,),
369 TcpOptionKind::SACK => (5,),
370 TcpOptionKind::ECHO => (6,),
371 TcpOptionKind::ECHO_REPLY => (7,),
372 TcpOptionKind::TIMESTAMPS => (8,),
373 TcpOptionKind::POCP => (9,),
374 TcpOptionKind::POSP => (10,),
375 TcpOptionKind::CC => (11,),
376 TcpOptionKind::CC_NEW => (12,),
377 TcpOptionKind::CC_ECHO => (13,),
378 TcpOptionKind::ALT_CHECKSUM_REQ => (14,),
379 TcpOptionKind::ALT_CHECKSUM_DATA => (15,),
380 TcpOptionKind::SKEETER => (16,),
381 TcpOptionKind::BUBBA => (17,),
382 TcpOptionKind::TRAILER_CHECKSUM => (18,),
383 TcpOptionKind::MD5_SIGNATURE => (19,),
384 TcpOptionKind::SCPS_CAPABILITIES => (20,),
385 TcpOptionKind::SELECTIVE_ACK => (21,),
386 TcpOptionKind::RECORD_BOUNDARIES => (22,),
387 TcpOptionKind::CORRUPTION_EXPERIENCED => (23,),
388 TcpOptionKind::SNAP => (24,),
389 TcpOptionKind::UNASSIGNED => (25,),
390 TcpOptionKind::TCP_COMPRESSION_FILTER => (26,),
391 TcpOptionKind::QUICK_START => (27,),
392 TcpOptionKind::USER_TIMEOUT => (28,),
393 TcpOptionKind::TCP_AO => (29,),
394 TcpOptionKind::MPTCP => (30,),
395 TcpOptionKind::RESERVED_31 => (31,),
396 TcpOptionKind::RESERVED_32 => (32,),
397 TcpOptionKind::RESERVED_33 => (33,),
398 TcpOptionKind::FAST_OPEN_COOKIE => (34,),
399 TcpOptionKind::TCP_ENO => (35,),
400 TcpOptionKind::ACC_ECNO_0 => (36,),
401 TcpOptionKind::ACC_ECNO_1 => (37,),
402 TcpOptionKind::EXPERIMENT_1 => (253,),
403 TcpOptionKind::EXPERIMENT_2 => (254,),
404 TcpOptionKind::RESERVED(n) => (n,),
405 }
406 }
407}
408
409#[packet]
411pub struct TcpOption {
412 #[construct_with(u8)]
413 kind: TcpOptionKind,
414 #[length_fn = "tcp_option_length"]
415 length: Vec<u8>,
418 #[length_fn = "tcp_option_payload_length"]
419 #[payload]
420 data: Vec<u8>,
421}
422
423impl TcpOption {
424 pub fn nop() -> Self {
426 TcpOption {
427 kind: TcpOptionKind::NOP,
428 length: vec![],
429 data: vec![],
430 }
431 }
432
433 pub fn timestamp(my: u32, their: u32) -> Self {
437 let mut data = vec![];
438 data.extend_from_slice(&my.octets()[..]);
439 data.extend_from_slice(&their.octets()[..]);
440
441 TcpOption {
442 kind: TcpOptionKind::TIMESTAMPS,
443 length: vec![10],
444 data: data,
445 }
446 }
447
448 pub fn mss(val: u16) -> Self {
451 let mut data = vec![];
452 data.extend_from_slice(&val.octets()[..]);
453
454 TcpOption {
455 kind: TcpOptionKind::MSS,
456 length: vec![4],
457 data: data,
458 }
459 }
460
461 pub fn wscale(val: u8) -> Self {
464 TcpOption {
465 kind: TcpOptionKind::WSCALE,
466 length: vec![3],
467 data: vec![val],
468 }
469 }
470
471 pub fn sack_perm() -> Self {
475 TcpOption {
476 kind: TcpOptionKind::SACK_PERMITTED,
477 length: vec![2],
478 data: vec![],
479 }
480 }
481
482 pub fn selective_ack(acks: &[u32]) -> Self {
487 let mut data = vec![];
488 for ack in acks {
489 data.extend_from_slice(&ack.octets()[..]);
490 }
491 TcpOption {
492 kind: TcpOptionKind::SACK,
493 length: vec![1 + 1 + data.len() as u8],
494 data: data,
495 }
496 }
497 pub fn kind(&self) -> TcpOptionKind {
499 self.kind
500 }
501 pub fn length(&self) -> u8 {
503 if self.length.is_empty() {
504 0
505 } else {
506 self.length[0]
507 }
508 }
509 pub fn get_timestamp(&self) -> (u32, u32) {
511 if self.kind == TcpOptionKind::TIMESTAMPS && self.data.len() >= 8 {
512 let mut my: [u8; 4] = [0; 4];
513 my.copy_from_slice(&self.data[0..4]);
514 let mut their: [u8; 4] = [0; 4];
515 their.copy_from_slice(&self.data[4..8]);
516 (u32::from_be_bytes(my), u32::from_be_bytes(their))
517 } else {
518 return (0, 0);
519 }
520 }
521 pub fn get_mss(&self) -> u16 {
523 if self.kind == TcpOptionKind::MSS && self.data.len() >= 2 {
524 let mut mss: [u8; 2] = [0; 2];
525 mss.copy_from_slice(&self.data[0..2]);
526 u16::from_be_bytes(mss)
527 } else {
528 0
529 }
530 }
531 pub fn get_wscale(&self) -> u8 {
533 if self.kind == TcpOptionKind::WSCALE && self.data.len() > 0 {
534 self.data[0]
535 } else {
536 0
537 }
538 }
539}
540
541#[inline]
545fn tcp_option_length(option: &TcpOptionPacket) -> usize {
546 match option.get_kind() {
547 TcpOptionKind::EOL => 0,
548 TcpOptionKind::NOP => 0,
549 _ => 1,
550 }
551}
552
553fn tcp_option_payload_length(ipv4_option: &TcpOptionPacket) -> usize {
554 match ipv4_option.get_length_raw().first() {
555 Some(len) if *len >= 2 => *len as usize - 2,
556 _ => 0,
557 }
558}
559
560#[inline]
561fn tcp_options_length(tcp: &TcpPacket) -> usize {
562 let data_offset = tcp.get_data_offset();
563
564 if data_offset > 5 {
565 data_offset as usize * 4 - 20
566 } else {
567 0
568 }
569}
570
571pub fn ipv4_checksum(packet: &TcpPacket, source: &Ipv4Addr, destination: &Ipv4Addr) -> u16 {
573 ipv4_checksum_adv(packet, &[], source, destination)
574}
575
576pub fn ipv4_checksum_adv(
584 packet: &TcpPacket,
585 extra_data: &[u8],
586 source: &Ipv4Addr,
587 destination: &Ipv4Addr,
588) -> u16 {
589 util::ipv4_checksum(
590 packet.packet(),
591 8,
592 extra_data,
593 source,
594 destination,
595 IpNextLevelProtocol::Tcp,
596 )
597}
598
599pub fn ipv6_checksum(packet: &TcpPacket, source: &Ipv6Addr, destination: &Ipv6Addr) -> u16 {
601 ipv6_checksum_adv(packet, &[], source, destination)
602}
603
604pub fn ipv6_checksum_adv(
612 packet: &TcpPacket,
613 extra_data: &[u8],
614 source: &Ipv6Addr,
615 destination: &Ipv6Addr,
616) -> u16 {
617 util::ipv6_checksum(
618 packet.packet(),
619 8,
620 extra_data,
621 source,
622 destination,
623 IpNextLevelProtocol::Tcp,
624 )
625}
626
627#[test]
628fn tcp_header_ipv4_test() {
629 use crate::ip::IpNextLevelProtocol;
630 use crate::ipv4::MutableIpv4Packet;
631
632 const IPV4_HEADER_LEN: usize = 20;
633 const TCP_HEADER_LEN: usize = 32;
634 const TEST_DATA_LEN: usize = 4;
635
636 let mut packet = [0u8; IPV4_HEADER_LEN + TCP_HEADER_LEN + TEST_DATA_LEN];
637 let ipv4_source = Ipv4Addr::new(192, 168, 2, 1);
638 let ipv4_destination = Ipv4Addr::new(192, 168, 111, 51);
639 {
640 let mut ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
641 ip_header.set_next_level_protocol(IpNextLevelProtocol::Tcp);
642 ip_header.set_source(ipv4_source);
643 ip_header.set_destination(ipv4_destination);
644 }
645
646 packet[IPV4_HEADER_LEN + TCP_HEADER_LEN] = 't' as u8;
648 packet[IPV4_HEADER_LEN + TCP_HEADER_LEN + 1] = 'e' as u8;
649 packet[IPV4_HEADER_LEN + TCP_HEADER_LEN + 2] = 's' as u8;
650 packet[IPV4_HEADER_LEN + TCP_HEADER_LEN + 3] = 't' as u8;
651
652 {
653 let mut tcp_header = MutableTcpPacket::new(&mut packet[IPV4_HEADER_LEN..]).unwrap();
654 tcp_header.set_source(49511);
655 assert_eq!(tcp_header.get_source(), 49511);
656
657 tcp_header.set_destination(9000);
658 assert_eq!(tcp_header.get_destination(), 9000);
659
660 tcp_header.set_sequence(0x9037d2b8);
661 assert_eq!(tcp_header.get_sequence(), 0x9037d2b8);
662
663 tcp_header.set_acknowledgement(0x944bb276);
664 assert_eq!(tcp_header.get_acknowledgement(), 0x944bb276);
665
666 tcp_header.set_flags(TcpFlags::PSH | TcpFlags::ACK);
667 assert_eq!(tcp_header.get_flags(), TcpFlags::PSH | TcpFlags::ACK);
668
669 tcp_header.set_window(4015);
670 assert_eq!(tcp_header.get_window(), 4015);
671
672 tcp_header.set_data_offset(8);
673 assert_eq!(tcp_header.get_data_offset(), 8);
674
675 let ts = TcpOption::timestamp(743951781, 44056978);
676 tcp_header.set_options(&vec![TcpOption::nop(), TcpOption::nop(), ts]);
677
678 let checksum = ipv4_checksum(&tcp_header.to_immutable(), &ipv4_source, &ipv4_destination);
679 tcp_header.set_checksum(checksum);
680 assert_eq!(tcp_header.get_checksum(), 0xc031);
681 }
682 let ref_packet = [
683 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, ];
694 assert_eq!(&ref_packet[..], &packet[20..]);
695}
696
697#[test]
698fn tcp_test_options_invalid_offset() {
699 let mut buf = [0; 20]; {
701 if let Some(mut tcp) = MutableTcpPacket::new(&mut buf[..]) {
702 tcp.set_data_offset(10); }
704 }
705
706 if let Some(tcp) = TcpPacket::new(&buf[..]) {
707 let _options = tcp.get_options_iter(); }
709}
710
711#[test]
712fn tcp_test_options_vec_invalid_offset() {
713 let mut buf = [0; 20]; {
715 if let Some(mut tcp) = MutableTcpPacket::new(&mut buf[..]) {
716 tcp.set_data_offset(10); }
718 }
719
720 if let Some(tcp) = TcpPacket::new(&buf[..]) {
721 let _options = tcp.get_options(); }
723}
724
725#[test]
726fn tcp_test_options_slice_invalid_offset() {
727 let mut buf = [0; 20]; {
729 if let Some(mut tcp) = MutableTcpPacket::new(&mut buf[..]) {
730 tcp.set_data_offset(10); }
732 }
733
734 if let Some(tcp) = TcpPacket::new(&buf[..]) {
735 let _options = tcp.get_options_raw(); }
737}
738
739#[test]
740fn tcp_test_option_invalid_len() {
741 use std::println;
742 let mut buf = [0; 24];
743 {
744 if let Some(mut tcp) = MutableTcpPacket::new(&mut buf[..]) {
745 tcp.set_data_offset(6);
746 }
747 buf[20] = 2; buf[21] = 8; }
750
751 if let Some(tcp) = TcpPacket::new(&buf[..]) {
752 let options = tcp.get_options_iter();
753 for opt in options {
754 println!("{:?}", opt);
755 }
756 }
757}
758
759#[test]
760fn tcp_test_payload_slice_invalid_offset() {
761 let mut buf = [0; 20];
762 {
763 if let Some(mut tcp) = MutableTcpPacket::new(&mut buf[..]) {
764 tcp.set_data_offset(10); }
766 }
767
768 if let Some(tcp) = TcpPacket::new(&buf[..]) {
769 assert_eq!(tcp.payload().len(), 0);
770 }
771}