1use alloc::vec;
4use alloc::vec::Vec;
5use core::net::Ipv4Addr;
6
7use crate::types::IpProtocol;
8use crate::util::{pseudo_header_checksum, seal_transport_checksum, read_u16be, read_u32be, write_u16be, write_u32be};
9
10pub const TCP_MIN_HEADER_LEN: usize = 20;
11
12const FLAG_FIN: u8 = 0x01;
14const FLAG_SYN: u8 = 0x02;
15const FLAG_RST: u8 = 0x04;
16const FLAG_PSH: u8 = 0x08;
17const FLAG_ACK: u8 = 0x10;
18const FLAG_URG: u8 = 0x20;
19
20const DEFAULT_DATA_OFFSET: u8 = 5;
22
23const OPT_END: u8 = 0;
25const OPT_NOOP: u8 = 1;
26const OPT_MSS: u8 = 2;
27const OPT_WINDOW_SCALE: u8 = 3;
28const OPT_SACK_PERMITTED: u8 = 4;
29const OPT_SACK: u8 = 5;
30const OPT_TIMESTAMP: u8 = 8;
31
32#[derive(Debug, Clone)]
34pub enum TcpOption {
35 EndOfList,
36 NoOp,
37 MaximumSegmentSize(u16),
38 WindowScale(u8),
39 SackPermitted,
40 Sack(Vec<(u32, u32)>),
41 Timestamp { ts_val: u32, ts_ecr: u32 },
42 Unknown { kind: u8, data: Vec<u8> },
43}
44
45pub struct TcpOptionsIter<'a> {
47 data: &'a [u8],
48}
49
50impl<'a> TcpOptionsIter<'a> {
51 fn new(data: &'a [u8]) -> Self {
52 Self { data }
53 }
54}
55
56impl<'a> Iterator for TcpOptionsIter<'a> {
57 type Item = TcpOption;
58
59 fn next(&mut self) -> Option<Self::Item> {
60 if self.data.is_empty() {
61 return None;
62 }
63 let kind = self.data[0];
64 match kind {
65 OPT_END => {
66 self.data = &[];
67 Some(TcpOption::EndOfList)
68 }
69 OPT_NOOP => {
70 self.data = &self.data[1..];
71 Some(TcpOption::NoOp)
72 }
73 OPT_MSS => {
74 if self.data.len() < 4 {
75 self.data = &[];
76 return Some(TcpOption::Unknown { kind, data: self.data.to_vec() });
77 }
78 let mss = read_u16be(&self.data[2..4]);
79 self.data = &self.data[4..];
80 Some(TcpOption::MaximumSegmentSize(mss))
81 }
82 OPT_WINDOW_SCALE => {
83 if self.data.len() < 3 {
84 self.data = &[];
85 return Some(TcpOption::Unknown { kind, data: self.data.to_vec() });
86 }
87 let shift = self.data[2];
88 self.data = &self.data[3..];
89 Some(TcpOption::WindowScale(shift))
90 }
91 OPT_SACK_PERMITTED => {
92 if self.data.len() < 2 {
93 self.data = &[];
94 return Some(TcpOption::Unknown { kind, data: self.data.to_vec() });
95 }
96 self.data = &self.data[2..];
97 Some(TcpOption::SackPermitted)
98 }
99 OPT_SACK => {
100 let len = self.data.get(1).copied().unwrap_or(0) as usize;
101 if len < 2 || self.data.len() < len {
102 self.data = &[];
103 return Some(TcpOption::Unknown { kind, data: self.data.to_vec() });
104 }
105 let blocks_data = &self.data[2..len];
106 let mut blocks = Vec::new();
107 for chunk in blocks_data.chunks(8) {
108 if chunk.len() == 8 {
109 blocks.push((read_u32be(&chunk[..4]), read_u32be(&chunk[4..8])));
110 }
111 }
112 self.data = &self.data[len..];
113 Some(TcpOption::Sack(blocks))
114 }
115 OPT_TIMESTAMP => {
116 if self.data.len() < 10 {
117 self.data = &[];
118 return Some(TcpOption::Unknown { kind, data: self.data.to_vec() });
119 }
120 let ts_val = read_u32be(&self.data[2..6]);
121 let ts_ecr = read_u32be(&self.data[6..10]);
122 self.data = &self.data[10..];
123 Some(TcpOption::Timestamp { ts_val, ts_ecr })
124 }
125 _ => {
126 let len = self.data.get(1).copied().unwrap_or(0) as usize;
127 if kind > 1 && len >= 2 && self.data.len() >= len {
128 let data = self.data[..len].to_vec();
129 self.data = &self.data[len..];
130 Some(TcpOption::Unknown { kind, data })
131 } else {
132 let remaining = self.data.to_vec();
133 self.data = &[];
134 Some(TcpOption::Unknown { kind, data: remaining })
135 }
136 }
137 }
138 }
139}
140
141#[derive(Debug, Clone)]
143pub struct TcpPacket<'a> {
144 buf: &'a [u8],
145}
146
147impl<'a> TcpPacket<'a> {
148 pub fn new(buf: &'a [u8]) -> Option<Self> {
149 if buf.len() < TCP_MIN_HEADER_LEN {
150 return None;
151 }
152 let data_offset = (buf[12] >> 4) as usize * 4;
153 if data_offset < TCP_MIN_HEADER_LEN || buf.len() < data_offset {
154 return None;
155 }
156 Some(Self { buf })
157 }
158
159 #[inline]
161 pub fn as_bytes(&self) -> &'a [u8] { self.buf }
162
163 #[inline]
164 pub fn source_port(&self) -> u16 {
165 read_u16be(&self.buf[..2])
166 }
167
168 #[inline]
169 pub fn destination_port(&self) -> u16 {
170 read_u16be(&self.buf[2..4])
171 }
172
173 #[inline]
174 pub fn sequence(&self) -> u32 {
175 read_u32be(&self.buf[4..8])
176 }
177
178 #[inline]
179 pub fn ack_number(&self) -> u32 {
180 read_u32be(&self.buf[8..12])
181 }
182
183 #[inline]
184 pub fn data_offset(&self) -> u8 {
185 self.buf[12] >> 4
186 }
187
188 #[inline]
189 pub fn flags(&self) -> u8 {
190 self.buf[13] & 0x3F
191 }
192
193 #[inline]
194 pub fn fin(&self) -> bool {
195 self.flags() & FLAG_FIN != 0
196 }
197
198 #[inline]
199 pub fn syn(&self) -> bool {
200 self.flags() & FLAG_SYN != 0
201 }
202
203 #[inline]
204 pub fn rst(&self) -> bool {
205 self.flags() & FLAG_RST != 0
206 }
207
208 #[inline]
209 pub fn psh(&self) -> bool {
210 self.flags() & FLAG_PSH != 0
211 }
212
213 #[inline]
214 pub fn ack(&self) -> bool {
215 self.flags() & FLAG_ACK != 0
216 }
217
218 #[inline]
219 pub fn urg(&self) -> bool {
220 self.flags() & FLAG_URG != 0
221 }
222
223 #[inline]
224 pub fn window(&self) -> u16 {
225 read_u16be(&self.buf[14..16])
226 }
227
228 #[inline]
229 pub fn checksum(&self) -> u16 {
230 read_u16be(&self.buf[16..18])
231 }
232
233 #[inline]
234 pub fn urgent_pointer(&self) -> u16 {
235 read_u16be(&self.buf[18..20])
236 }
237
238 pub fn options(&self) -> TcpOptionsIter<'a> {
240 let hdr_len = self.header_length();
241 if hdr_len > TCP_MIN_HEADER_LEN {
242 TcpOptionsIter::new(&self.buf[TCP_MIN_HEADER_LEN..hdr_len])
243 } else {
244 TcpOptionsIter::new(&[])
245 }
246 }
247
248 #[inline]
250 pub fn payload(&self) -> &'a [u8] {
251 &self.buf[self.header_length()..]
252 }
253
254 #[inline]
255 pub fn header_length(&self) -> usize {
256 self.data_offset() as usize * 4
257 }
258
259 pub fn verify_checksum(&self, src: Ipv4Addr, dst: Ipv4Addr) -> bool {
261 pseudo_header_checksum(
262 &src.octets(),
263 &dst.octets(),
264 IpProtocol::Tcp.into(),
265 self.buf,
266 ) == 0
267 }
268}
269
270pub struct TcpPacketBuilder {
275 buf: Vec<u8>,
276 options: Vec<u8>,
277 payload: Option<Vec<u8>>,
278}
279
280impl Default for TcpPacketBuilder {
281 fn default() -> Self {
282 Self::new()
283 }
284}
285
286impl TcpPacketBuilder {
287 pub fn new() -> Self {
288 let mut buf = vec![0u8; TCP_MIN_HEADER_LEN];
289 buf[12] = DEFAULT_DATA_OFFSET << 4;
290 Self { buf, options: Vec::new(), payload: None }
291 }
292
293 pub fn source_port(mut self, port: u16) -> Self {
294 write_u16be(&mut self.buf[..2], port);
295 self
296 }
297
298 pub fn destination_port(mut self, port: u16) -> Self {
299 write_u16be(&mut self.buf[2..4], port);
300 self
301 }
302
303 pub fn sequence(mut self, seq: u32) -> Self {
304 write_u32be(&mut self.buf[4..8], seq);
305 self
306 }
307
308 pub fn ack_number(mut self, ack: u32) -> Self {
309 write_u32be(&mut self.buf[8..12], ack);
310 self
311 }
312
313 pub fn window(mut self, w: u16) -> Self {
314 write_u16be(&mut self.buf[14..16], w);
315 self
316 }
317
318 pub fn urgent_pointer(mut self, up: u16) -> Self {
319 write_u16be(&mut self.buf[18..20], up);
320 self
321 }
322
323 pub fn syn(mut self, on: bool) -> Self {
324 if on { self.buf[13] |= FLAG_SYN; } else { self.buf[13] &= !FLAG_SYN; }
325 self
326 }
327
328 pub fn ack(mut self, on: bool) -> Self {
329 if on { self.buf[13] |= FLAG_ACK; } else { self.buf[13] &= !FLAG_ACK; }
330 self
331 }
332
333 pub fn fin(mut self, on: bool) -> Self {
334 if on { self.buf[13] |= FLAG_FIN; } else { self.buf[13] &= !FLAG_FIN; }
335 self
336 }
337
338 pub fn rst(mut self, on: bool) -> Self {
339 if on { self.buf[13] |= FLAG_RST; } else { self.buf[13] &= !FLAG_RST; }
340 self
341 }
342
343 pub fn psh(mut self, on: bool) -> Self {
344 if on { self.buf[13] |= FLAG_PSH; } else { self.buf[13] &= !FLAG_PSH; }
345 self
346 }
347
348 pub fn urg(mut self, on: bool) -> Self {
349 if on { self.buf[13] |= FLAG_URG; } else { self.buf[13] &= !FLAG_URG; }
350 self
351 }
352
353 pub fn add_option(mut self, data: &[u8]) -> Self {
355 self.options.extend_from_slice(data);
356 self
357 }
358
359 pub fn mss(mut self, mss: u16) -> Self {
361 self.options.push(OPT_MSS);
362 self.options.push(4);
363 self.options.extend_from_slice(&mss.to_be_bytes());
364 self
365 }
366
367 pub fn window_scale(mut self, shift: u8) -> Self {
369 self.options.push(OPT_WINDOW_SCALE);
370 self.options.push(3);
371 self.options.push(shift);
372 self
373 }
374
375 pub fn sack_permitted(mut self) -> Self {
377 self.options.push(OPT_SACK_PERMITTED);
378 self.options.push(2);
379 self
380 }
381
382 pub fn timestamp(mut self, ts_val: u32, ts_ecr: u32) -> Self {
384 self.options.push(OPT_TIMESTAMP);
385 self.options.push(10);
386 self.options.extend_from_slice(&ts_val.to_be_bytes());
387 self.options.extend_from_slice(&ts_ecr.to_be_bytes());
388 self
389 }
390
391 pub fn payload(mut self, data: &[u8]) -> Self {
392 self.payload = Some(data.to_vec());
393 self
394 }
395
396 pub fn build(mut self, src: Ipv4Addr, dst: Ipv4Addr) -> Vec<u8> {
398 while !self.options.len().is_multiple_of(4) {
400 self.options.push(OPT_NOOP);
401 }
402 let total_hdr_words = (TCP_MIN_HEADER_LEN + self.options.len()) / 4;
404 self.buf[12] = (total_hdr_words as u8) << 4;
405
406 let mut packet = self.buf;
407 if !self.options.is_empty() {
408 packet.extend_from_slice(&self.options);
409 }
410 if let Some(ref p) = self.payload {
411 packet.extend_from_slice(p);
412 }
413 seal_transport_checksum(&mut packet, 16, &src.octets(), &dst.octets(), IpProtocol::Tcp.into());
414 packet
415 }
416}
417
418#[cfg(test)]
423mod tests {
424 use super::*;
425
426 fn sample_tcp_syn() -> Vec<u8> {
428 let mut data = vec![0u8; TCP_MIN_HEADER_LEN];
429 write_u16be(&mut data[..2], 1234);
430 write_u16be(&mut data[2..4], 80);
431 write_u32be(&mut data[4..8], 1); write_u32be(&mut data[8..12], 0); data[12] = DEFAULT_DATA_OFFSET << 4;
434 data[13] = FLAG_SYN;
435 write_u16be(&mut data[14..16], 65535); data
437 }
438
439 #[test]
440 fn parse_tcp_no_options() {
441 let data = sample_tcp_syn();
442 let pkt = TcpPacket::new(&data).unwrap();
443 assert_eq!(pkt.source_port(), 1234);
444 assert_eq!(pkt.destination_port(), 80);
445 assert_eq!(pkt.sequence(), 1);
446 assert_eq!(pkt.ack_number(), 0);
447 assert_eq!(pkt.data_offset(), 5);
448 assert_eq!(pkt.header_length(), 20);
449 assert!(pkt.syn());
450 assert!(!pkt.ack());
451 assert!(!pkt.fin());
452 assert!(!pkt.rst());
453 assert_eq!(pkt.window(), 65535);
454 }
455
456 #[test]
457 fn parse_tcp_too_short() {
458 assert!(TcpPacket::new(&[]).is_none());
459 assert!(TcpPacket::new(&[0u8; 19]).is_none());
460 let mut d = [0u8; 20];
462 d[12] = DEFAULT_DATA_OFFSET << 4;
463 assert!(TcpPacket::new(&d).is_some());
464 }
465
466 #[test]
467 fn parse_tcp_data_offset_exceeds_buffer() {
468 let mut data = vec![0u8; 22];
469 data[12] = 0x60; assert!(TcpPacket::new(&data).is_none());
471 }
472
473 #[test]
474 fn tcp_options_mss_and_window_scale() {
475 let mut data = sample_tcp_syn();
476 data.extend_from_slice(&[OPT_MSS, 4, 0x05, 0xB4]);
478 data.extend_from_slice(&[OPT_WINDOW_SCALE, 3, 7]);
480 data.push(OPT_NOOP);
482 data[12] = 0x70;
484
485 let pkt = TcpPacket::new(&data).unwrap();
486 assert_eq!(pkt.data_offset(), 7);
487 assert_eq!(pkt.header_length(), 28);
488
489 let opts: Vec<_> = pkt.options().collect();
490 assert_eq!(opts.len(), 3); match &opts[0] {
492 TcpOption::MaximumSegmentSize(mss) => assert_eq!(*mss, 1460),
493 _ => panic!("expected MSS"),
494 }
495 match &opts[1] {
496 TcpOption::WindowScale(shift) => assert_eq!(*shift, 7),
497 _ => panic!("expected WindowScale"),
498 }
499 }
500
501 #[test]
502 fn tcp_options_timestamp() {
503 let mut data = sample_tcp_syn();
504 data.extend_from_slice(&[OPT_TIMESTAMP, 10,
505 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, ]);
508 data.push(OPT_NOOP);
510 data.push(OPT_NOOP);
511 data[12] = 0x80; let pkt = TcpPacket::new(&data).unwrap();
514 let opts: Vec<_> = pkt.options().collect();
515 match &opts[0] {
516 TcpOption::Timestamp { ts_val, ts_ecr } => {
517 assert_eq!(*ts_val, 1);
518 assert_eq!(*ts_ecr, 2);
519 }
520 _ => panic!("expected Timestamp"),
521 }
522 }
523
524 #[test]
525 fn tcp_options_sack() {
526 let mut data = sample_tcp_syn();
527 data.extend_from_slice(&[OPT_SACK, 18]);
529 data.extend_from_slice(&100u32.to_be_bytes());
531 data.extend_from_slice(&200u32.to_be_bytes());
532 data.extend_from_slice(&300u32.to_be_bytes());
534 data.extend_from_slice(&400u32.to_be_bytes());
535 data.push(OPT_NOOP);
537 data.push(OPT_NOOP);
538 data[12] = 0xA0; let pkt = TcpPacket::new(&data).unwrap();
541 let opts: Vec<_> = pkt.options().collect();
542 match &opts[0] {
543 TcpOption::Sack(blocks) => {
544 assert_eq!(blocks.len(), 2);
545 assert_eq!(blocks[0], (100, 200));
546 assert_eq!(blocks[1], (300, 400));
547 }
548 _ => panic!("expected SACK"),
549 }
550 }
551
552 #[test]
553 fn tcp_sack_permitted() {
554 let mut data = sample_tcp_syn();
555 data.extend_from_slice(&[OPT_SACK_PERMITTED, 2]);
556 data.push(OPT_NOOP);
557 data.push(OPT_NOOP);
558 data[12] = 0x60; let pkt = TcpPacket::new(&data).unwrap();
561 let opts: Vec<_> = pkt.options().collect();
562 assert!(matches!(opts[0], TcpOption::SackPermitted));
563 }
564
565 #[test]
566 fn tcp_build_and_verify_checksum() {
567 let src = Ipv4Addr::new(10, 0, 0, 1);
568 let dst = Ipv4Addr::new(10, 0, 0, 2);
569 let pkt_bytes = TcpPacketBuilder::new()
570 .source_port(12345)
571 .destination_port(80)
572 .sequence(1000)
573 .syn(true)
574 .window(65535)
575 .mss(1460)
576 .build(src, dst);
577
578 let pkt = TcpPacket::new(&pkt_bytes).unwrap();
579 assert!(pkt.syn());
580 assert_eq!(pkt.source_port(), 12345);
581 assert_eq!(pkt.destination_port(), 80);
582 assert_eq!(pkt.sequence(), 1000);
583 assert!(pkt.verify_checksum(src, dst));
584 }
585
586 #[test]
587 fn tcp_build_roundtrip_with_options() {
588 let src = Ipv4Addr::new(192, 168, 1, 1);
589 let dst = Ipv4Addr::new(192, 168, 1, 2);
590 let pkt_bytes = TcpPacketBuilder::new()
591 .source_port(54321)
592 .destination_port(443)
593 .sequence(0x12345678)
594 .ack_number(0x87654321)
595 .syn(true)
596 .ack(true)
597 .window(8192)
598 .mss(1460)
599 .window_scale(7)
600 .sack_permitted()
601 .timestamp(0x100, 0x200)
602 .payload(&[0x01, 0x02, 0x03])
603 .build(src, dst);
604
605 let pkt = TcpPacket::new(&pkt_bytes).unwrap();
606 assert_eq!(pkt.source_port(), 54321);
607 assert_eq!(pkt.destination_port(), 443);
608 assert_eq!(pkt.sequence(), 0x12345678);
609 assert_eq!(pkt.ack_number(), 0x87654321);
610 assert!(pkt.syn());
611 assert!(pkt.ack());
612 assert_eq!(pkt.window(), 8192);
613 assert_eq!(pkt.payload(), &[0x01, 0x02, 0x03]);
614 assert!(pkt.verify_checksum(src, dst));
615
616 let opts: Vec<_> = pkt.options().collect();
618 assert!(opts.iter().any(|o| matches!(o, TcpOption::MaximumSegmentSize(1460))));
619 assert!(opts.iter().any(|o| matches!(o, TcpOption::WindowScale(7))));
620 assert!(opts.iter().any(|o| matches!(o, TcpOption::SackPermitted)));
621 assert!(opts.iter().any(|o| matches!(o, TcpOption::Timestamp { ts_val: 0x100, ts_ecr: 0x200 })));
622 }
623
624 #[test]
625 fn tcp_end_of_list_option() {
626 let mut data = sample_tcp_syn();
627 data.push(OPT_END); data.extend_from_slice(&[OPT_MSS, 4, 0x05, 0xB4]); data.push(OPT_NOOP);
630 data.push(OPT_NOOP);
631 data[12] = 0x60;
632
633 let pkt = TcpPacket::new(&data).unwrap();
634 let opts: Vec<_> = pkt.options().collect();
635 assert_eq!(opts.len(), 1);
636 assert!(matches!(opts[0], TcpOption::EndOfList));
637 }
638}