stackforge_core/layer/tcp/
builder.rs1use std::net::{Ipv4Addr, Ipv6Addr};
26
27use super::checksum::{tcp_checksum_ipv4, tcp_checksum_ipv6};
28use super::flags::TcpFlags;
29use super::header::{TCP_MIN_HEADER_LEN, TcpLayer, offsets};
30use super::options::{TcpAoValue, TcpOption, TcpOptions, TcpOptionsBuilder, TcpSackBlock};
31use crate::layer::field::FieldError;
32
33#[derive(Debug, Clone)]
35pub struct TcpBuilder {
36 src_port: u16,
38 dst_port: u16,
39 seq: u32,
40 ack: u32,
41 data_offset: Option<u8>,
42 reserved: u8,
43 flags: TcpFlags,
44 window: u16,
45 checksum: Option<u16>,
46 urgent_ptr: u16,
47
48 options: TcpOptions,
50
51 payload: Vec<u8>,
53
54 auto_checksum: bool,
56 auto_data_offset: bool,
57
58 src_ip: Option<IpAddr>,
60 dst_ip: Option<IpAddr>,
61
62 flags_explicitly_set: bool,
65}
66
67#[derive(Debug, Clone, Copy)]
69pub enum IpAddr {
70 V4(Ipv4Addr),
71 V6(Ipv6Addr),
72}
73
74impl From<Ipv4Addr> for IpAddr {
75 fn from(addr: Ipv4Addr) -> Self {
76 IpAddr::V4(addr)
77 }
78}
79
80impl From<Ipv6Addr> for IpAddr {
81 fn from(addr: Ipv6Addr) -> Self {
82 IpAddr::V6(addr)
83 }
84}
85
86impl Default for TcpBuilder {
87 fn default() -> Self {
88 Self {
89 src_port: 20,
90 dst_port: 80,
91 seq: 0,
92 ack: 0,
93 data_offset: None,
94 reserved: 0,
95 flags: TcpFlags::from_u16(0x02), window: 8192,
97 checksum: None,
98 urgent_ptr: 0,
99 options: TcpOptions::new(),
100 payload: Vec::new(),
101 auto_checksum: true,
102 auto_data_offset: true,
103 src_ip: None,
104 dst_ip: None,
105 flags_explicitly_set: false,
106 }
107 }
108}
109
110impl TcpBuilder {
111 pub fn new() -> Self {
113 Self::default()
114 }
115
116 pub fn from_bytes(data: &[u8]) -> Result<Self, FieldError> {
118 let layer = TcpLayer::at_offset_dynamic(data, 0)?;
119
120 let mut builder = Self::new();
121 builder.src_port = layer.src_port(data)?;
122 builder.dst_port = layer.dst_port(data)?;
123 builder.seq = layer.seq(data)?;
124 builder.ack = layer.ack(data)?;
125 builder.data_offset = Some(layer.data_offset(data)?);
126 builder.reserved = layer.reserved(data)?;
127 builder.flags = layer.flags(data)?;
128 builder.window = layer.window(data)?;
129 builder.checksum = Some(layer.checksum(data)?);
130 builder.urgent_ptr = layer.urgent_ptr(data)?;
131
132 if layer.options_len(data) > 0 {
134 builder.options = layer.options(data)?;
135 }
136
137 let header_len = layer.calculate_header_len(data);
139 if data.len() > header_len {
140 builder.payload = data[header_len..].to_vec();
141 }
142
143 builder.auto_checksum = false;
145 builder.auto_data_offset = false;
146
147 Ok(builder)
148 }
149
150 pub fn src_port(mut self, port: u16) -> Self {
154 self.src_port = port;
155 self
156 }
157
158 pub fn sport(self, port: u16) -> Self {
160 self.src_port(port)
161 }
162
163 pub fn dst_port(mut self, port: u16) -> Self {
165 self.dst_port = port;
166 self
167 }
168
169 pub fn dport(self, port: u16) -> Self {
171 self.dst_port(port)
172 }
173
174 pub fn seq(mut self, seq: u32) -> Self {
176 self.seq = seq;
177 self
178 }
179
180 pub fn ack_num(mut self, ack: u32) -> Self {
182 self.ack = ack;
183 self
184 }
185
186 pub fn data_offset(mut self, offset: u8) -> Self {
188 self.data_offset = Some(offset);
189 self.auto_data_offset = false;
190 self
191 }
192
193 pub fn dataofs(self, offset: u8) -> Self {
195 self.data_offset(offset)
196 }
197
198 pub fn reserved(mut self, reserved: u8) -> Self {
200 self.reserved = reserved & 0x07;
201 self
202 }
203
204 pub fn flags(mut self, flags: TcpFlags) -> Self {
206 self.flags = flags;
207 self.flags_explicitly_set = true;
208 self
209 }
210
211 pub fn flags_str(mut self, s: &str) -> Self {
213 self.flags = TcpFlags::from_str(s);
214 self.flags_explicitly_set = true;
215 self
216 }
217
218 fn clear_defaults_if_needed(&mut self) {
223 if !self.flags_explicitly_set {
224 self.flags = TcpFlags::from_u16(0);
225 self.flags_explicitly_set = true;
226 }
227 }
228
229 pub fn syn(mut self) -> Self {
231 self.clear_defaults_if_needed();
232 self.flags.syn = true;
233 self
234 }
235
236 pub fn ack(mut self) -> Self {
238 self.clear_defaults_if_needed();
239 self.flags.ack = true;
240 self
241 }
242
243 pub fn fin(mut self) -> Self {
245 self.clear_defaults_if_needed();
246 self.flags.fin = true;
247 self
248 }
249
250 pub fn rst(mut self) -> Self {
252 self.clear_defaults_if_needed();
253 self.flags.rst = true;
254 self
255 }
256
257 pub fn psh(mut self) -> Self {
259 self.clear_defaults_if_needed();
260 self.flags.psh = true;
261 self
262 }
263
264 pub fn urg(mut self) -> Self {
266 self.clear_defaults_if_needed();
267 self.flags.urg = true;
268 self
269 }
270
271 pub fn ece(mut self) -> Self {
273 self.clear_defaults_if_needed();
274 self.flags.ece = true;
275 self
276 }
277
278 pub fn cwr(mut self) -> Self {
280 self.clear_defaults_if_needed();
281 self.flags.cwr = true;
282 self
283 }
284
285 pub fn ns(mut self) -> Self {
287 self.clear_defaults_if_needed();
288 self.flags.ns = true;
289 self
290 }
291
292 pub fn syn_ack(mut self) -> Self {
294 self.clear_defaults_if_needed();
295 self.flags.syn = true;
296 self.flags.ack = true;
297 self
298 }
299
300 pub fn fin_ack(mut self) -> Self {
302 self.clear_defaults_if_needed();
303 self.flags.fin = true;
304 self.flags.ack = true;
305 self
306 }
307
308 pub fn psh_ack(mut self) -> Self {
310 self.clear_defaults_if_needed();
311 self.flags.psh = true;
312 self.flags.ack = true;
313 self
314 }
315
316 pub fn window(mut self, window: u16) -> Self {
318 self.window = window;
319 self
320 }
321
322 pub fn checksum(mut self, checksum: u16) -> Self {
324 self.checksum = Some(checksum);
325 self.auto_checksum = false;
326 self
327 }
328
329 pub fn chksum(self, checksum: u16) -> Self {
331 self.checksum(checksum)
332 }
333
334 pub fn urgent_ptr(mut self, urgptr: u16) -> Self {
336 self.urgent_ptr = urgptr;
337 self
338 }
339
340 pub fn urgptr(self, urgptr: u16) -> Self {
342 self.urgent_ptr(urgptr)
343 }
344
345 pub fn src_ip<T: Into<IpAddr>>(mut self, ip: T) -> Self {
349 self.src_ip = Some(ip.into());
350 self
351 }
352
353 pub fn dst_ip<T: Into<IpAddr>>(mut self, ip: T) -> Self {
355 self.dst_ip = Some(ip.into());
356 self
357 }
358
359 pub fn ipv4_addrs(mut self, src: Ipv4Addr, dst: Ipv4Addr) -> Self {
361 self.src_ip = Some(IpAddr::V4(src));
362 self.dst_ip = Some(IpAddr::V4(dst));
363 self
364 }
365
366 pub fn ipv6_addrs(mut self, src: Ipv6Addr, dst: Ipv6Addr) -> Self {
368 self.src_ip = Some(IpAddr::V6(src));
369 self.dst_ip = Some(IpAddr::V6(dst));
370 self
371 }
372
373 pub fn options(mut self, options: TcpOptions) -> Self {
377 self.options = options;
378 self
379 }
380
381 pub fn option(mut self, option: TcpOption) -> Self {
383 self.options.push(option);
384 self
385 }
386
387 pub fn with_options<F>(mut self, f: F) -> Self
389 where
390 F: FnOnce(TcpOptionsBuilder) -> TcpOptionsBuilder,
391 {
392 self.options = f(TcpOptionsBuilder::new()).build();
393 self
394 }
395
396 pub fn mss(mut self, mss: u16) -> Self {
398 self.options.push(TcpOption::Mss(mss));
399 self
400 }
401
402 pub fn wscale(mut self, scale: u8) -> Self {
404 self.options.push(TcpOption::WScale(scale));
405 self
406 }
407
408 pub fn sack_ok(mut self) -> Self {
410 self.options.push(TcpOption::SackOk);
411 self
412 }
413
414 pub fn sack(mut self, blocks: Vec<TcpSackBlock>) -> Self {
416 self.options.push(TcpOption::Sack(blocks));
417 self
418 }
419
420 pub fn timestamp(mut self, ts_val: u32, ts_ecr: u32) -> Self {
422 self.options.push(TcpOption::timestamp(ts_val, ts_ecr));
423 self
424 }
425
426 pub fn nop(mut self) -> Self {
428 self.options.push(TcpOption::Nop);
429 self
430 }
431
432 pub fn eol(mut self) -> Self {
434 self.options.push(TcpOption::Eol);
435 self
436 }
437
438 pub fn tfo(mut self, cookie: Option<Vec<u8>>) -> Self {
440 self.options.push(TcpOption::Tfo { cookie });
441 self
442 }
443
444 pub fn md5(mut self, signature: [u8; 16]) -> Self {
446 self.options.push(TcpOption::Md5(signature));
447 self
448 }
449
450 pub fn ao(mut self, key_id: u8, rnext_key_id: u8, mac: Vec<u8>) -> Self {
452 self.options
453 .push(TcpOption::Ao(TcpAoValue::new(key_id, rnext_key_id, mac)));
454 self
455 }
456
457 pub fn payload(mut self, payload: impl Into<Vec<u8>>) -> Self {
461 self.payload = payload.into();
462 self
463 }
464
465 pub fn append_payload(mut self, data: &[u8]) -> Self {
467 self.payload.extend_from_slice(data);
468 self
469 }
470
471 pub fn auto_checksum(mut self, enabled: bool) -> Self {
475 self.auto_checksum = enabled;
476 self
477 }
478
479 pub fn auto_data_offset(mut self, enabled: bool) -> Self {
481 self.auto_data_offset = enabled;
482 self
483 }
484
485 pub fn header_size(&self) -> usize {
489 if let Some(doff) = self.data_offset {
490 (doff as usize) * 4
491 } else {
492 let opts_len = self.options.padded_len();
493 TCP_MIN_HEADER_LEN + opts_len
494 }
495 }
496
497 pub fn packet_size(&self) -> usize {
499 self.header_size() + self.payload.len()
500 }
501
502 pub fn build(&self) -> Vec<u8> {
504 let total_size = self.packet_size();
505 let mut buf = vec![0u8; total_size];
506 self.build_into(&mut buf)
507 .expect("buffer is correctly sized");
508 buf
509 }
510
511 pub fn build_into(&self, buf: &mut [u8]) -> Result<usize, FieldError> {
513 let header_size = self.header_size();
514 let total_size = self.packet_size();
515
516 if buf.len() < total_size {
517 return Err(FieldError::BufferTooShort {
518 offset: 0,
519 need: total_size,
520 have: buf.len(),
521 });
522 }
523
524 let data_offset = if self.auto_data_offset {
526 (header_size / 4) as u8
527 } else {
528 self.data_offset.unwrap_or(5)
529 };
530
531 buf[offsets::SRC_PORT] = (self.src_port >> 8) as u8;
533 buf[offsets::SRC_PORT + 1] = (self.src_port & 0xFF) as u8;
534
535 buf[offsets::DST_PORT] = (self.dst_port >> 8) as u8;
537 buf[offsets::DST_PORT + 1] = (self.dst_port & 0xFF) as u8;
538
539 buf[offsets::SEQ..offsets::SEQ + 4].copy_from_slice(&self.seq.to_be_bytes());
541
542 buf[offsets::ACK..offsets::ACK + 4].copy_from_slice(&self.ack.to_be_bytes());
544
545 buf[offsets::DATA_OFFSET] =
547 ((data_offset & 0x0F) << 4) | ((self.reserved & 0x07) << 1) | self.flags.ns_bit();
548
549 buf[offsets::FLAGS] = self.flags.to_byte();
551
552 buf[offsets::WINDOW] = (self.window >> 8) as u8;
554 buf[offsets::WINDOW + 1] = (self.window & 0xFF) as u8;
555
556 buf[offsets::CHECKSUM] = 0;
558 buf[offsets::CHECKSUM + 1] = 0;
559
560 buf[offsets::URG_PTR] = (self.urgent_ptr >> 8) as u8;
562 buf[offsets::URG_PTR + 1] = (self.urgent_ptr & 0xFF) as u8;
563
564 if !self.options.is_empty() {
566 let opts_bytes = self.options.to_bytes();
567 let opts_end = offsets::OPTIONS + opts_bytes.len();
568 if opts_end <= header_size {
569 buf[offsets::OPTIONS..opts_end].copy_from_slice(&opts_bytes);
570 }
571 }
572
573 if !self.payload.is_empty() {
575 buf[header_size..header_size + self.payload.len()].copy_from_slice(&self.payload);
576 }
577
578 let checksum = if self.auto_checksum {
580 match (self.src_ip, self.dst_ip) {
581 (Some(IpAddr::V4(src)), Some(IpAddr::V4(dst))) => {
582 tcp_checksum_ipv4(src, dst, &buf[..total_size])
583 }
584 (Some(IpAddr::V6(src)), Some(IpAddr::V6(dst))) => {
585 tcp_checksum_ipv6(src, dst, &buf[..total_size])
586 }
587 _ => 0, }
589 } else {
590 self.checksum.unwrap_or(0)
591 };
592 buf[offsets::CHECKSUM] = (checksum >> 8) as u8;
593 buf[offsets::CHECKSUM + 1] = (checksum & 0xFF) as u8;
594
595 Ok(total_size)
596 }
597
598 pub fn build_header(&self) -> Vec<u8> {
600 let header_size = self.header_size();
601 let mut buf = vec![0u8; header_size];
602
603 let builder = Self {
605 payload: Vec::new(),
606 ..self.clone()
607 };
608 builder
609 .build_into(&mut buf)
610 .expect("buffer is correctly sized");
611
612 buf
613 }
614}
615
616impl TcpBuilder {
619 pub fn syn_packet() -> Self {
621 Self::new().syn().ack_num(0)
622 }
623
624 pub fn syn_ack_packet() -> Self {
626 Self::new().syn_ack()
627 }
628
629 pub fn ack_packet() -> Self {
631 Self::new().flags(TcpFlags::A)
632 }
633
634 pub fn fin_ack_packet() -> Self {
636 Self::new().fin_ack()
637 }
638
639 pub fn rst_packet() -> Self {
641 Self::new().flags(TcpFlags::R)
642 }
643
644 pub fn rst_ack_packet() -> Self {
646 Self::new().flags(TcpFlags::RA)
647 }
648
649 pub fn data_packet() -> Self {
651 Self::new().psh_ack()
652 }
653}
654
655#[cfg(feature = "rand")]
658impl TcpBuilder {
659 pub fn random_seq(mut self) -> Self {
661 use rand::Rng;
662 self.seq = rand::rng().random();
663 self
664 }
665
666 pub fn random_sport(mut self) -> Self {
668 use rand::Rng;
669 self.src_port = rand::rng().random_range(49152..=65535);
670 self
671 }
672}
673
674#[cfg(test)]
675mod tests {
676 use super::*;
677
678 #[test]
679 fn test_basic_build() {
680 let pkt = TcpBuilder::new()
681 .src_port(12345)
682 .dst_port(80)
683 .seq(1000)
684 .syn()
685 .window(65535)
686 .build();
687
688 assert_eq!(pkt.len(), 20); let layer = TcpLayer::at_offset(0);
691 assert_eq!(layer.src_port(&pkt).unwrap(), 12345);
692 assert_eq!(layer.dst_port(&pkt).unwrap(), 80);
693 assert_eq!(layer.seq(&pkt).unwrap(), 1000);
694 assert_eq!(layer.window(&pkt).unwrap(), 65535);
695
696 let flags = layer.flags(&pkt).unwrap();
697 assert!(flags.syn);
698 assert!(!flags.ack);
699 }
700
701 #[test]
702 fn test_with_options() {
703 let pkt = TcpBuilder::new()
704 .src_port(12345)
705 .dst_port(80)
706 .syn()
707 .mss(1460)
708 .wscale(7)
709 .sack_ok()
710 .nop()
711 .build();
712
713 let layer = TcpLayer::at_offset(0);
714 let opts = layer.options(&pkt).unwrap();
715
716 assert_eq!(opts.mss(), Some(1460));
717 assert_eq!(opts.wscale(), Some(7));
718 assert!(opts.sack_permitted());
719 }
720
721 #[test]
722 fn test_with_payload() {
723 let payload = b"Hello, TCP!";
724 let pkt = TcpBuilder::new()
725 .src_port(12345)
726 .dst_port(80)
727 .psh_ack()
728 .payload(payload.to_vec())
729 .build();
730
731 assert_eq!(pkt.len(), 20 + payload.len());
732
733 let layer = TcpLayer::at_offset(0);
734 let pkt_payload = layer.payload(&pkt);
735 assert_eq!(pkt_payload, payload);
736 }
737
738 #[test]
739 fn test_with_checksum() {
740 let src_ip = Ipv4Addr::new(192, 168, 1, 1);
741 let dst_ip = Ipv4Addr::new(192, 168, 1, 2);
742
743 let pkt = TcpBuilder::new()
744 .src_port(12345)
745 .dst_port(80)
746 .syn()
747 .ipv4_addrs(src_ip, dst_ip)
748 .build();
749
750 let layer = TcpLayer::at_offset(0);
751 let checksum = layer.checksum(&pkt).unwrap();
752 assert_ne!(checksum, 0);
753 }
754
755 #[test]
756 fn test_flags() {
757 let pkt = TcpBuilder::new().syn_ack().build();
758
759 let layer = TcpLayer::at_offset(0);
760 let flags = layer.flags(&pkt).unwrap();
761 assert!(flags.syn);
762 assert!(flags.ack);
763
764 let pkt = TcpBuilder::new().fin_ack().build();
765 let flags = layer.flags(&pkt).unwrap();
766 assert!(flags.fin);
767 assert!(flags.ack);
768 }
769
770 #[test]
771 fn test_from_bytes() {
772 let original = TcpBuilder::new()
773 .src_port(12345)
774 .dst_port(443)
775 .seq(0xDEADBEEF)
776 .ack_num(0xCAFEBABE)
777 .syn_ack()
778 .window(32768)
779 .mss(1460)
780 .build();
781
782 let rebuilt = TcpBuilder::from_bytes(&original)
783 .unwrap()
784 .auto_checksum(false)
785 .build();
786
787 assert_eq!(original.len(), rebuilt.len());
788
789 let layer = TcpLayer::at_offset(0);
790 assert_eq!(
791 layer.src_port(&original).unwrap(),
792 layer.src_port(&rebuilt).unwrap()
793 );
794 assert_eq!(
795 layer.dst_port(&original).unwrap(),
796 layer.dst_port(&rebuilt).unwrap()
797 );
798 assert_eq!(layer.seq(&original).unwrap(), layer.seq(&rebuilt).unwrap());
799 assert_eq!(layer.ack(&original).unwrap(), layer.ack(&rebuilt).unwrap());
800 }
801
802 #[test]
803 fn test_convenience_constructors() {
804 let syn = TcpBuilder::syn_packet().build();
805 let layer = TcpLayer::at_offset(0);
806 let flags = layer.flags(&syn).unwrap();
807 assert!(flags.syn);
808 assert!(!flags.ack);
809
810 let syn_ack = TcpBuilder::syn_ack_packet().build();
811 let flags = layer.flags(&syn_ack).unwrap();
812 assert!(flags.syn);
813 assert!(flags.ack);
814
815 let rst = TcpBuilder::rst_packet().build();
816 let flags = layer.flags(&rst).unwrap();
817 assert!(flags.rst);
818 }
819
820 #[test]
821 fn test_timestamp_option() {
822 let pkt = TcpBuilder::new()
823 .syn()
824 .mss(1460)
825 .timestamp(12345, 0)
826 .build();
827
828 let layer = TcpLayer::at_offset(0);
829 let opts = layer.options(&pkt).unwrap();
830
831 let ts = opts.timestamp().unwrap();
832 assert_eq!(ts.ts_val, 12345);
833 assert_eq!(ts.ts_ecr, 0);
834 }
835
836 #[test]
837 fn test_tfo_option() {
838 let cookie = vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
839 let pkt = TcpBuilder::new().syn().tfo(Some(cookie.clone())).build();
840
841 let layer = TcpLayer::at_offset(0);
842 let opts = layer.options(&pkt).unwrap();
843
844 assert_eq!(opts.tfo_cookie(), Some(cookie.as_slice()));
845 }
846
847 #[test]
848 fn test_flags_str() {
849 let pkt = TcpBuilder::new().flags_str("SA").build();
850
851 let layer = TcpLayer::at_offset(0);
852 let flags = layer.flags(&pkt).unwrap();
853 assert!(flags.syn);
854 assert!(flags.ack);
855
856 let pkt = TcpBuilder::new().flags_str("FA").build();
857 let flags = layer.flags(&pkt).unwrap();
858 assert!(flags.fin);
859 assert!(flags.ack);
860 }
861}