1pub mod opt;
92
93use std::fmt::{self, Formatter};
94use std::ops::Deref;
95
96use smol_str::{SmolStr, SmolStrBuilder};
97use zerocopy::byteorder::{BigEndian, U16, U32};
98use zerocopy::{FromBytes, IntoBytes, Unaligned};
99
100use crate::packet::tcp::opt::TcpOptionsIter;
101use crate::packet::{HeaderParser, PacketHeader};
102
103#[repr(C, packed)]
108#[derive(
109 FromBytes, IntoBytes, Unaligned, Debug, Clone, Copy, zerocopy::KnownLayout, zerocopy::Immutable,
110)]
111pub struct TcpHeader {
112 src_port: U16<BigEndian>,
113 dst_port: U16<BigEndian>,
114 sequence_number: U32<BigEndian>,
115 acknowledgment_number: U32<BigEndian>,
116 data_offset_flags: U16<BigEndian>,
117 window_size: U16<BigEndian>,
118 checksum: U16<BigEndian>,
119 urgent_pointer: U16<BigEndian>,
120}
121
122impl TcpHeader {
123 pub const FLAG_FIN: u8 = 0x01;
125 pub const FLAG_SYN: u8 = 0x02;
126 pub const FLAG_RST: u8 = 0x04;
127 pub const FLAG_PSH: u8 = 0x08;
128 pub const FLAG_ACK: u8 = 0x10;
129 pub const FLAG_URG: u8 = 0x20;
130 pub const FLAG_ECE: u8 = 0x40;
131 pub const FLAG_CWR: u8 = 0x80;
132
133 #[allow(unused)]
134 const NAME: &'static str = "TcpHeader";
135
136 #[inline]
138 pub fn data_offset(&self) -> u8 {
139 (self.data_offset_flags.get() >> 12) as u8
140 }
141
142 #[inline]
144 pub fn flags(&self) -> u8 {
145 (self.data_offset_flags.get() & 0x00FF) as u8
146 }
147
148 #[inline]
150 pub fn has_fin(&self) -> bool {
151 self.flags() & Self::FLAG_FIN != 0
152 }
153
154 #[inline]
156 pub fn has_syn(&self) -> bool {
157 self.flags() & Self::FLAG_SYN != 0
158 }
159
160 #[inline]
162 pub fn has_rst(&self) -> bool {
163 self.flags() & Self::FLAG_RST != 0
164 }
165
166 #[inline]
168 pub fn has_psh(&self) -> bool {
169 self.flags() & Self::FLAG_PSH != 0
170 }
171
172 #[inline]
174 pub fn has_ack(&self) -> bool {
175 self.flags() & Self::FLAG_ACK != 0
176 }
177
178 #[inline]
180 pub fn has_urg(&self) -> bool {
181 self.flags() & Self::FLAG_URG != 0
182 }
183
184 #[inline]
186 pub fn has_ece(&self) -> bool {
187 self.flags() & Self::FLAG_ECE != 0
188 }
189
190 #[inline]
192 pub fn has_cwr(&self) -> bool {
193 self.flags() & Self::FLAG_CWR != 0
194 }
195
196 #[inline]
198 pub fn src_port(&self) -> u16 {
199 self.src_port.get()
200 }
201
202 #[inline]
204 pub fn dst_port(&self) -> u16 {
205 self.dst_port.get()
206 }
207
208 #[inline]
210 pub fn sequence_number(&self) -> u32 {
211 self.sequence_number.get()
212 }
213
214 #[inline]
216 fn is_valid(&self) -> bool {
217 let offset = self.data_offset();
220 (5..=15).contains(&offset)
221 }
222
223 #[inline]
225 pub fn acknowledgment_number(&self) -> u32 {
226 self.acknowledgment_number.get()
227 }
228
229 #[inline]
231 pub fn window_size(&self) -> u16 {
232 self.window_size.get()
233 }
234
235 #[inline]
237 pub fn urgent_pointer(&self) -> u16 {
238 self.urgent_pointer.get()
239 }
240
241 pub fn flags_string(&self) -> SmolStr {
243 let mut result = SmolStrBuilder::new();
244 if self.has_fin() {
245 result.push('F');
246 }
247 if self.has_syn() {
248 result.push('S');
249 }
250 if self.has_rst() {
251 result.push('R');
252 }
253 if self.has_psh() {
254 result.push('P');
255 }
256 if self.has_ack() {
257 result.push('A');
258 }
259 if self.has_urg() {
260 result.push('U');
261 }
262 if self.has_ece() {
263 result.push('E');
264 }
265 if self.has_cwr() {
266 result.push('C');
267 }
268 result.finish()
269 }
270}
271
272#[derive(Debug, Clone)]
273pub struct TcpHeaderOpt<'a> {
274 pub header: &'a TcpHeader,
275 pub raw_options: &'a [u8],
276}
277
278impl<'a> TcpHeaderOpt<'a> {
279 pub fn options(&'a self) -> TcpOptionsIter<'a> {
281 TcpOptionsIter::new(self.raw_options)
282 }
283}
284
285impl Deref for TcpHeaderOpt<'_> {
286 type Target = TcpHeader;
287
288 #[inline]
289 fn deref(&self) -> &Self::Target {
290 self.header
291 }
292}
293
294impl PacketHeader for TcpHeader {
295 const NAME: &'static str = "TcpHeader";
296 type InnerType = ();
297
298 #[inline]
299 fn inner_type(&self) -> Self::InnerType {}
300
301 #[inline]
303 fn total_len(&self, _buf: &[u8]) -> usize {
304 (self.data_offset() as usize) * 4
305 }
306
307 #[inline]
309 fn is_valid(&self) -> bool {
310 self.is_valid()
311 }
312}
313
314impl HeaderParser for TcpHeader {
315 type Output<'a> = TcpHeaderOpt<'a>;
316
317 #[inline]
318 fn into_view<'a>(header: &'a Self, raw_options: &'a [u8]) -> Self::Output<'a> {
319 TcpHeaderOpt {
320 header,
321 raw_options,
322 }
323 }
324}
325
326impl fmt::Display for TcpHeader {
327 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
328 write!(
329 f,
330 "TCP {} -> {} [{}] seq={} ack={} win={}",
331 self.src_port(),
332 self.dst_port(),
333 self.flags_string(),
334 self.sequence_number(),
335 self.acknowledgment_number(),
336 self.window_size()
337 )?;
338
339 if self.data_offset() > 5 {
340 write!(f, " +opts")?;
341 }
342
343 Ok(())
344 }
345}
346
347impl fmt::Display for TcpHeaderOpt<'_> {
348 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
349 write!(f, "{}", self.header)?;
350
351 if !self.raw_options.is_empty() {
352 write!(f, " opts=[")?;
353 let mut first = true;
354 for opt in self.options().flatten() {
355 if !first {
356 write!(f, ",")?;
357 }
358 first = false;
359 write!(f, "{}", opt)?;
360 }
361 write!(f, "]")?;
362 }
363
364 Ok(())
365 }
366}
367
368#[cfg(test)]
369mod tests {
370 use super::*;
371
372 #[test]
373 fn test_tcp_flags() {
374 let header = TcpHeader {
375 src_port: U16::new(80),
376 dst_port: U16::new(12345),
377 sequence_number: U32::new(0),
378 acknowledgment_number: U32::new(0),
379 data_offset_flags: U16::new((5 << 12) | TcpHeader::FLAG_SYN as u16),
380 window_size: U16::new(65535),
381 checksum: U16::new(0),
382 urgent_pointer: U16::new(0),
383 };
384
385 let buf = [0u8; 20];
387
388 assert_eq!(header.data_offset(), 5);
389 assert_eq!(header.total_len(&buf), 20);
390 assert!(header.has_syn());
391 assert!(!header.has_ack());
392 assert!(header.is_valid());
393 }
394
395 #[test]
396 fn test_tcp_header_validation() {
397 let mut header = TcpHeader {
398 src_port: U16::new(80),
399 dst_port: U16::new(12345),
400 sequence_number: U32::new(0),
401 acknowledgment_number: U32::new(0),
402 data_offset_flags: U16::new(4 << 12), window_size: U16::new(65535),
404 checksum: U16::new(0),
405 urgent_pointer: U16::new(0),
406 };
407
408 assert!(!header.is_valid());
409
410 header.data_offset_flags = U16::new(5 << 12);
411 assert!(header.is_valid());
412 }
413
414 #[test]
415 fn test_tcp_header_size() {
416 assert_eq!(std::mem::size_of::<TcpHeader>(), 20);
417 assert_eq!(TcpHeader::FIXED_LEN, 20);
418 }
419
420 #[test]
421 fn test_tcp_all_flags() {
422 let mut header = create_test_header();
423
424 header.data_offset_flags = U16::new((5 << 12) | TcpHeader::FLAG_FIN as u16);
426 assert!(header.has_fin());
427 assert!(!header.has_syn());
428
429 header.data_offset_flags = U16::new((5 << 12) | TcpHeader::FLAG_SYN as u16);
430 assert!(header.has_syn());
431 assert!(!header.has_fin());
432
433 header.data_offset_flags = U16::new((5 << 12) | TcpHeader::FLAG_RST as u16);
434 assert!(header.has_rst());
435
436 header.data_offset_flags = U16::new((5 << 12) | TcpHeader::FLAG_PSH as u16);
437 assert!(header.has_psh());
438
439 header.data_offset_flags = U16::new((5 << 12) | TcpHeader::FLAG_ACK as u16);
440 assert!(header.has_ack());
441
442 header.data_offset_flags = U16::new((5 << 12) | TcpHeader::FLAG_URG as u16);
443 assert!(header.has_urg());
444
445 header.data_offset_flags = U16::new((5 << 12) | TcpHeader::FLAG_ECE as u16);
446 assert!(header.has_ece());
447
448 header.data_offset_flags = U16::new((5 << 12) | TcpHeader::FLAG_CWR as u16);
449 assert!(header.has_cwr());
450
451 header.data_offset_flags =
453 U16::new((5 << 12) | (TcpHeader::FLAG_SYN | TcpHeader::FLAG_ACK) as u16);
454 assert!(header.has_syn());
455 assert!(header.has_ack());
456 assert_eq!(header.flags_string(), "SA");
457 }
458
459 #[test]
460 fn test_tcp_parsing_basic() {
461 let packet = create_test_packet();
462
463 let result = TcpHeader::from_bytes(&packet);
464 assert!(result.is_ok());
465
466 let (header, payload) = result.unwrap();
467 assert_eq!(header.src_port(), 54321);
468 assert_eq!(header.dst_port(), 80);
469 assert_eq!(header.data_offset(), 5);
470 assert!(header.has_syn());
471 assert!(header.is_valid());
472 assert_eq!(payload.len(), 0); }
474
475 #[test]
476 fn test_tcp_parsing_too_small() {
477 let packet = vec![0u8; 19]; let result = TcpHeader::from_bytes(&packet);
480 assert!(result.is_err());
481 }
482
483 #[test]
484 fn test_tcp_total_len_no_options() {
485 let packet = create_test_packet();
486 let (header, _) = TcpHeader::from_bytes(&packet).unwrap();
487
488 assert_eq!(header.total_len(&packet), 20);
490 assert_eq!(header.data_offset(), 5);
491 }
492
493 #[test]
494 fn test_tcp_with_mss_option() {
495 let mut packet = create_test_packet();
496
497 packet[12] = 0x60; packet[13] = 0x02; packet.push(0x02); packet.push(0x04); packet.extend_from_slice(&1460u16.to_be_bytes()); let (header, _) = TcpHeader::from_bytes(&packet).unwrap();
507
508 assert_eq!(header.data_offset(), 6);
510 assert_eq!(header.total_len(&packet), 24); assert!(header.is_valid());
512
513 let options_len = (header.data_offset() as usize * 4) - TcpHeader::FIXED_LEN;
515 let options_start = TcpHeader::FIXED_LEN;
516 let raw_options = &packet[options_start..options_start + options_len];
517
518 assert_eq!(raw_options.len(), 4);
519 assert_eq!(raw_options[0], 0x02); assert_eq!(raw_options[1], 0x04); }
522
523 #[test]
524 fn test_tcp_with_window_scale_option() {
525 let mut packet = create_test_packet();
526
527 packet[12] = 0x60;
529 packet[13] = 0x02; packet.push(0x03); packet.push(0x03); packet.push(0x07); packet.push(0x01); let (header, _) = TcpHeader::from_bytes(&packet).unwrap();
538
539 assert_eq!(header.data_offset(), 6);
540 assert_eq!(header.total_len(&packet), 24);
541
542 let options_len = (header.data_offset() as usize * 4) - TcpHeader::FIXED_LEN;
543 let options_start = TcpHeader::FIXED_LEN;
544 let raw_options = &packet[options_start..options_start + options_len];
545
546 assert_eq!(raw_options.len(), 4);
547 assert_eq!(raw_options[0], 0x03); assert_eq!(raw_options[2], 0x07); }
550
551 #[test]
552 fn test_tcp_with_timestamp_option() {
553 let mut packet = create_test_packet();
554
555 packet[12] = 0x80;
557 packet[13] = 0x02; packet.push(0x08); packet.push(0x0A); packet.extend_from_slice(&12345678u32.to_be_bytes()); packet.extend_from_slice(&87654321u32.to_be_bytes()); packet.push(0x01); packet.push(0x01); let (header, _) = TcpHeader::from_bytes(&packet).unwrap();
570
571 assert_eq!(header.data_offset(), 8);
572 assert_eq!(header.total_len(&packet), 32);
573
574 let options_len = (header.data_offset() as usize * 4) - TcpHeader::FIXED_LEN;
575 let options_start = TcpHeader::FIXED_LEN;
576 let raw_options = &packet[options_start..options_start + options_len];
577
578 assert_eq!(raw_options.len(), 12);
579 assert_eq!(raw_options[0], 0x08); assert_eq!(raw_options[1], 0x0A); }
582
583 #[test]
584 fn test_tcp_with_sack_permitted_option() {
585 let mut packet = create_test_packet();
586
587 packet[12] = 0x60;
589 packet[13] = 0x02; packet.push(0x04); packet.push(0x02); packet.push(0x01); packet.push(0x01); let (header, _) = TcpHeader::from_bytes(&packet).unwrap();
598
599 assert_eq!(header.data_offset(), 6);
600 assert_eq!(header.total_len(&packet), 24);
601
602 let options_len = (header.data_offset() as usize * 4) - TcpHeader::FIXED_LEN;
603 let options_start = TcpHeader::FIXED_LEN;
604 let raw_options = &packet[options_start..options_start + options_len];
605
606 assert_eq!(raw_options[0], 0x04); }
608
609 #[test]
610 fn test_tcp_with_multiple_options() {
611 let mut packet = create_test_packet();
612
613 packet[12] = 0xA0;
615 packet[13] = 0x02; packet.push(0x02); packet.push(0x04); packet.extend_from_slice(&1460u16.to_be_bytes());
622
623 packet.push(0x04); packet.push(0x02); packet.push(0x08); packet.push(0x0A); packet.extend_from_slice(&12345u32.to_be_bytes()); packet.extend_from_slice(&0u32.to_be_bytes()); packet.push(0x03); packet.push(0x03); packet.push(0x07); packet.push(0x01); let (header, _) = TcpHeader::from_bytes(&packet).unwrap();
640
641 assert_eq!(header.data_offset(), 10);
642 assert_eq!(header.total_len(&packet), 40);
643
644 let options_len = (header.data_offset() as usize * 4) - TcpHeader::FIXED_LEN;
645 let options_start = TcpHeader::FIXED_LEN;
646 let raw_options = &packet[options_start..options_start + options_len];
647
648 assert_eq!(raw_options.len(), 20);
649 assert_eq!(raw_options[0], 0x02); assert_eq!(raw_options[4], 0x04); assert_eq!(raw_options[6], 0x08); assert_eq!(raw_options[16], 0x03); }
654
655 #[test]
656 fn test_tcp_from_bytes_with_options_and_payload() {
657 let mut packet = create_test_packet();
658
659 packet[12] = 0x70;
661 packet[13] = 0x18; packet.push(0x02); packet.push(0x04); packet.extend_from_slice(&1460u16.to_be_bytes());
667 packet.extend_from_slice(&[0x01, 0x01, 0x01, 0x01]); let payload_data = b"HTTP/1.1 200 OK\r\n";
671 packet.extend_from_slice(payload_data);
672
673 let result = TcpHeader::from_bytes(&packet);
674 assert!(result.is_ok());
675
676 let (header, payload) = result.unwrap();
677
678 assert_eq!(payload.len(), payload_data.len());
681 assert_eq!(payload, payload_data);
682
683 assert_eq!(header.data_offset(), 7);
685 assert_eq!(header.total_len(&packet), 28);
686 assert!(header.has_psh());
687 assert!(header.has_ack());
688 }
689
690 #[test]
691 fn test_tcp_total_len_includes_options() {
692 let mut packet = create_test_packet();
694
695 let (header, _) = TcpHeader::from_bytes(&packet).unwrap();
697 assert_eq!(header.total_len(&packet), 20);
698 assert_eq!(header.data_offset(), 5);
699
700 packet = create_test_packet();
702 packet[12] = 0x60; packet.extend_from_slice(&[0x01, 0x01, 0x01, 0x01]); let (header, _) = TcpHeader::from_bytes(&packet).unwrap();
705 assert_eq!(header.total_len(&packet), 24); assert_eq!(header.data_offset(), 6);
707
708 packet = create_test_packet();
710 packet[12] = 0x70;
711 packet.extend_from_slice(&[0x01; 8]); let (header, _) = TcpHeader::from_bytes(&packet).unwrap();
713 assert_eq!(header.total_len(&packet), 28); assert_eq!(header.data_offset(), 7);
715
716 packet = create_test_packet();
718 packet[12] = 0xF0; packet.extend_from_slice(&[0x01; 40]); let (header, _) = TcpHeader::from_bytes(&packet).unwrap();
721 assert_eq!(header.total_len(&packet), 60); assert_eq!(header.data_offset(), 15);
723 }
724
725 #[test]
726 fn test_tcp_options_extraction() {
727 let mut packet = create_test_packet();
728
729 let (header, _) = TcpHeader::from_bytes(&packet).unwrap();
731 let options_len = (header.data_offset() as usize * 4) - TcpHeader::FIXED_LEN;
732 assert_eq!(options_len, 0);
733
734 packet = create_test_packet();
736 packet[12] = 0x60;
737 packet.extend_from_slice(&[0x02, 0x04, 0x05, 0xb4]); let (header, _) = TcpHeader::from_bytes(&packet).unwrap();
739 let options_len = (header.data_offset() as usize * 4) - TcpHeader::FIXED_LEN;
740 let options_start = TcpHeader::FIXED_LEN;
741 let raw_options = &packet[options_start..options_start + options_len];
742 assert_eq!(raw_options.len(), 4);
743 }
744
745 #[test]
746 fn test_tcp_flags_string() {
747 let mut header = create_test_header();
748
749 header.data_offset_flags = U16::new(5 << 12);
750 assert_eq!(header.flags_string(), "");
751
752 header.data_offset_flags = U16::new((5 << 12) | TcpHeader::FLAG_SYN as u16);
753 assert_eq!(header.flags_string(), "S");
754
755 header.data_offset_flags =
756 U16::new((5 << 12) | (TcpHeader::FLAG_SYN | TcpHeader::FLAG_ACK) as u16);
757 assert_eq!(header.flags_string(), "SA");
758
759 header.data_offset_flags = U16::new(
760 (5 << 12) | (TcpHeader::FLAG_FIN | TcpHeader::FLAG_PSH | TcpHeader::FLAG_ACK) as u16,
761 );
762 assert_eq!(header.flags_string(), "FPA");
763
764 header.data_offset_flags = U16::new((5 << 12) | 0xFF);
766 assert_eq!(header.flags_string(), "FSRPAUEC");
767 }
768
769 #[test]
770 fn test_tcp_sequence_and_ack_numbers() {
771 let mut header = create_test_header();
772
773 header.sequence_number = U32::new(1000);
774 header.acknowledgment_number = U32::new(2000);
775
776 assert_eq!(header.sequence_number(), 1000);
777 assert_eq!(header.acknowledgment_number(), 2000);
778 }
779
780 #[test]
781 fn test_tcp_window_and_urgent() {
782 let mut header = create_test_header();
783
784 header.window_size = U16::new(65535);
785 header.urgent_pointer = U16::new(100);
786
787 assert_eq!(header.window_size(), 65535);
788 assert_eq!(header.urgent_pointer(), 100);
789 }
790
791 fn create_test_header() -> TcpHeader {
793 TcpHeader {
794 src_port: U16::new(80),
795 dst_port: U16::new(12345),
796 sequence_number: U32::new(0),
797 acknowledgment_number: U32::new(0),
798 data_offset_flags: U16::new(5 << 12), window_size: U16::new(65535),
800 checksum: U16::new(0),
801 urgent_pointer: U16::new(0),
802 }
803 }
804
805 fn create_test_packet() -> Vec<u8> {
807 let mut packet = Vec::new();
808
809 packet.extend_from_slice(&54321u16.to_be_bytes());
811
812 packet.extend_from_slice(&80u16.to_be_bytes());
814
815 packet.extend_from_slice(&1000u32.to_be_bytes());
817
818 packet.extend_from_slice(&0u32.to_be_bytes());
820
821 packet.extend_from_slice(&0x5002u16.to_be_bytes()); packet.extend_from_slice(&65535u16.to_be_bytes());
826
827 packet.extend_from_slice(&0u16.to_be_bytes());
829
830 packet.extend_from_slice(&0u16.to_be_bytes());
832
833 packet
834 }
835}