stackforge_core/layer/tcp/
flags.rs1use std::fmt;
7
8#[derive(Clone, Copy, PartialEq, Eq, Default, Hash)]
23pub struct TcpFlags {
24 pub fin: bool,
26 pub syn: bool,
28 pub rst: bool,
30 pub psh: bool,
32 pub ack: bool,
34 pub urg: bool,
36 pub ece: bool,
38 pub cwr: bool,
40 pub ns: bool,
42}
43
44impl TcpFlags {
45 pub const NONE: Self = Self {
47 fin: false,
48 syn: false,
49 rst: false,
50 psh: false,
51 ack: false,
52 urg: false,
53 ece: false,
54 cwr: false,
55 ns: false,
56 };
57
58 pub const S: Self = Self {
60 fin: false,
61 syn: true,
62 rst: false,
63 psh: false,
64 ack: false,
65 urg: false,
66 ece: false,
67 cwr: false,
68 ns: false,
69 };
70
71 pub const SA: Self = Self {
73 fin: false,
74 syn: true,
75 rst: false,
76 psh: false,
77 ack: true,
78 urg: false,
79 ece: false,
80 cwr: false,
81 ns: false,
82 };
83
84 pub const A: Self = Self {
86 fin: false,
87 syn: false,
88 rst: false,
89 psh: false,
90 ack: true,
91 urg: false,
92 ece: false,
93 cwr: false,
94 ns: false,
95 };
96
97 pub const FA: Self = Self {
99 fin: true,
100 syn: false,
101 rst: false,
102 psh: false,
103 ack: true,
104 urg: false,
105 ece: false,
106 cwr: false,
107 ns: false,
108 };
109
110 pub const R: Self = Self {
112 fin: false,
113 syn: false,
114 rst: true,
115 psh: false,
116 ack: false,
117 urg: false,
118 ece: false,
119 cwr: false,
120 ns: false,
121 };
122
123 pub const RA: Self = Self {
125 fin: false,
126 syn: false,
127 rst: true,
128 psh: false,
129 ack: true,
130 urg: false,
131 ece: false,
132 cwr: false,
133 ns: false,
134 };
135
136 pub const PA: Self = Self {
138 fin: false,
139 syn: false,
140 rst: false,
141 psh: true,
142 ack: true,
143 urg: false,
144 ece: false,
145 cwr: false,
146 ns: false,
147 };
148
149 pub const FIN_BIT: u16 = 0x001;
151 pub const SYN_BIT: u16 = 0x002;
152 pub const RST_BIT: u16 = 0x004;
153 pub const PSH_BIT: u16 = 0x008;
154 pub const ACK_BIT: u16 = 0x010;
155 pub const URG_BIT: u16 = 0x020;
156 pub const ECE_BIT: u16 = 0x040;
157 pub const CWR_BIT: u16 = 0x080;
158 pub const NS_BIT: u16 = 0x100;
159
160 #[inline]
164 pub fn from_u16(value: u16) -> Self {
165 Self {
166 fin: (value & Self::FIN_BIT) != 0,
167 syn: (value & Self::SYN_BIT) != 0,
168 rst: (value & Self::RST_BIT) != 0,
169 psh: (value & Self::PSH_BIT) != 0,
170 ack: (value & Self::ACK_BIT) != 0,
171 urg: (value & Self::URG_BIT) != 0,
172 ece: (value & Self::ECE_BIT) != 0,
173 cwr: (value & Self::CWR_BIT) != 0,
174 ns: (value & Self::NS_BIT) != 0,
175 }
176 }
177
178 #[inline]
180 pub fn from_byte(byte: u8) -> Self {
181 Self::from_u16(byte as u16)
182 }
183
184 #[inline]
186 pub fn from_bytes(hi: u8, lo: u8) -> Self {
187 let ns = (hi & 0x01) != 0;
188 let mut flags = Self::from_byte(lo);
189 flags.ns = ns;
190 flags
191 }
192
193 #[inline]
195 pub fn to_u16(self) -> u16 {
196 let mut value = 0u16;
197 if self.fin {
198 value |= Self::FIN_BIT;
199 }
200 if self.syn {
201 value |= Self::SYN_BIT;
202 }
203 if self.rst {
204 value |= Self::RST_BIT;
205 }
206 if self.psh {
207 value |= Self::PSH_BIT;
208 }
209 if self.ack {
210 value |= Self::ACK_BIT;
211 }
212 if self.urg {
213 value |= Self::URG_BIT;
214 }
215 if self.ece {
216 value |= Self::ECE_BIT;
217 }
218 if self.cwr {
219 value |= Self::CWR_BIT;
220 }
221 if self.ns {
222 value |= Self::NS_BIT;
223 }
224 value
225 }
226
227 #[inline]
229 pub fn to_byte(self) -> u8 {
230 (self.to_u16() & 0xFF) as u8
231 }
232
233 #[inline]
235 pub fn ns_bit(self) -> u8 {
236 if self.ns { 0x01 } else { 0x00 }
237 }
238
239 pub fn from_str(s: &str) -> Self {
242 let mut flags = Self::NONE;
243 for c in s.chars() {
244 match c {
245 'F' | 'f' => flags.fin = true,
246 'S' | 's' => flags.syn = true,
247 'R' | 'r' => flags.rst = true,
248 'P' | 'p' => flags.psh = true,
249 'A' | 'a' => flags.ack = true,
250 'U' | 'u' => flags.urg = true,
251 'E' | 'e' => flags.ece = true,
252 'C' | 'c' => flags.cwr = true,
253 'N' | 'n' => flags.ns = true,
254 _ => {}, }
256 }
257 flags
258 }
259
260 #[inline]
262 pub fn is_syn(&self) -> bool {
263 self.syn && !self.ack
264 }
265
266 #[inline]
268 pub fn is_syn_ack(&self) -> bool {
269 self.syn && self.ack
270 }
271
272 #[inline]
274 pub fn is_ack(&self) -> bool {
275 self.ack && !self.syn && !self.fin && !self.rst
276 }
277
278 #[inline]
280 pub fn is_fin(&self) -> bool {
281 self.fin
282 }
283
284 #[inline]
286 pub fn is_rst(&self) -> bool {
287 self.rst
288 }
289
290 #[inline]
292 pub fn has_ecn(&self) -> bool {
293 self.ece || self.cwr
294 }
295
296 #[inline]
298 pub fn is_empty(&self) -> bool {
299 !self.fin
300 && !self.syn
301 && !self.rst
302 && !self.psh
303 && !self.ack
304 && !self.urg
305 && !self.ece
306 && !self.cwr
307 && !self.ns
308 }
309
310 #[inline]
312 pub fn count(&self) -> u8 {
313 let mut count = 0;
314 if self.fin {
315 count += 1;
316 }
317 if self.syn {
318 count += 1;
319 }
320 if self.rst {
321 count += 1;
322 }
323 if self.psh {
324 count += 1;
325 }
326 if self.ack {
327 count += 1;
328 }
329 if self.urg {
330 count += 1;
331 }
332 if self.ece {
333 count += 1;
334 }
335 if self.cwr {
336 count += 1;
337 }
338 if self.ns {
339 count += 1;
340 }
341 count
342 }
343}
344
345impl fmt::Display for TcpFlags {
346 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
347 let mut s = String::with_capacity(9);
349 if self.fin {
350 s.push('F');
351 }
352 if self.syn {
353 s.push('S');
354 }
355 if self.rst {
356 s.push('R');
357 }
358 if self.psh {
359 s.push('P');
360 }
361 if self.ack {
362 s.push('A');
363 }
364 if self.urg {
365 s.push('U');
366 }
367 if self.ece {
368 s.push('E');
369 }
370 if self.cwr {
371 s.push('C');
372 }
373 if self.ns {
374 s.push('N');
375 }
376
377 if s.is_empty() {
378 write!(f, "-")
379 } else {
380 write!(f, "{}", s)
381 }
382 }
383}
384
385impl fmt::Debug for TcpFlags {
386 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
387 write!(f, "TcpFlags({})", self)
388 }
389}
390
391impl From<u16> for TcpFlags {
392 fn from(value: u16) -> Self {
393 Self::from_u16(value)
394 }
395}
396
397impl From<u8> for TcpFlags {
398 fn from(value: u8) -> Self {
399 Self::from_byte(value)
400 }
401}
402
403impl From<TcpFlags> for u16 {
404 fn from(flags: TcpFlags) -> Self {
405 flags.to_u16()
406 }
407}
408
409impl From<TcpFlags> for u8 {
410 fn from(flags: TcpFlags) -> Self {
411 flags.to_byte()
412 }
413}
414
415impl From<&str> for TcpFlags {
416 fn from(s: &str) -> Self {
417 Self::from_str(s)
418 }
419}
420
421impl std::ops::BitOr for TcpFlags {
422 type Output = Self;
423
424 fn bitor(self, rhs: Self) -> Self::Output {
425 Self {
426 fin: self.fin || rhs.fin,
427 syn: self.syn || rhs.syn,
428 rst: self.rst || rhs.rst,
429 psh: self.psh || rhs.psh,
430 ack: self.ack || rhs.ack,
431 urg: self.urg || rhs.urg,
432 ece: self.ece || rhs.ece,
433 cwr: self.cwr || rhs.cwr,
434 ns: self.ns || rhs.ns,
435 }
436 }
437}
438
439impl std::ops::BitAnd for TcpFlags {
440 type Output = Self;
441
442 fn bitand(self, rhs: Self) -> Self::Output {
443 Self {
444 fin: self.fin && rhs.fin,
445 syn: self.syn && rhs.syn,
446 rst: self.rst && rhs.rst,
447 psh: self.psh && rhs.psh,
448 ack: self.ack && rhs.ack,
449 urg: self.urg && rhs.urg,
450 ece: self.ece && rhs.ece,
451 cwr: self.cwr && rhs.cwr,
452 ns: self.ns && rhs.ns,
453 }
454 }
455}
456
457impl std::ops::BitOrAssign for TcpFlags {
458 fn bitor_assign(&mut self, rhs: Self) {
459 *self = *self | rhs;
460 }
461}
462
463impl std::ops::BitAndAssign for TcpFlags {
464 fn bitand_assign(&mut self, rhs: Self) {
465 *self = *self & rhs;
466 }
467}
468
469#[cfg(test)]
470mod tests {
471 use super::*;
472
473 #[test]
474 fn test_from_u16() {
475 let flags = TcpFlags::from_u16(0x02); assert!(flags.syn);
477 assert!(!flags.ack);
478 assert!(!flags.fin);
479
480 let flags = TcpFlags::from_u16(0x12); assert!(flags.syn);
482 assert!(flags.ack);
483
484 let flags = TcpFlags::from_u16(0x10); assert!(!flags.syn);
486 assert!(flags.ack);
487
488 let flags = TcpFlags::from_u16(0x11); assert!(flags.fin);
490 assert!(flags.ack);
491
492 let flags = TcpFlags::from_u16(0x04); assert!(flags.rst);
494
495 let flags = TcpFlags::from_u16(0x100); assert!(flags.ns);
497 }
498
499 #[test]
500 fn test_to_u16() {
501 assert_eq!(TcpFlags::S.to_u16(), 0x02);
502 assert_eq!(TcpFlags::SA.to_u16(), 0x12);
503 assert_eq!(TcpFlags::A.to_u16(), 0x10);
504 assert_eq!(TcpFlags::FA.to_u16(), 0x11);
505 assert_eq!(TcpFlags::R.to_u16(), 0x04);
506 }
507
508 #[test]
509 fn test_from_str() {
510 let flags = TcpFlags::from_str("S");
511 assert!(flags.syn);
512 assert!(!flags.ack);
513
514 let flags = TcpFlags::from_str("SA");
515 assert!(flags.syn);
516 assert!(flags.ack);
517
518 let flags = TcpFlags::from_str("FSRPAUECN");
519 assert!(flags.fin);
520 assert!(flags.syn);
521 assert!(flags.rst);
522 assert!(flags.psh);
523 assert!(flags.ack);
524 assert!(flags.urg);
525 assert!(flags.ece);
526 assert!(flags.cwr);
527 assert!(flags.ns);
528 }
529
530 #[test]
531 fn test_display() {
532 assert_eq!(TcpFlags::S.to_string(), "S");
533 assert_eq!(TcpFlags::SA.to_string(), "SA");
534 assert_eq!(TcpFlags::FA.to_string(), "FA");
535 assert_eq!(TcpFlags::PA.to_string(), "PA");
536 assert_eq!(TcpFlags::NONE.to_string(), "-");
537 }
538
539 #[test]
540 fn test_is_methods() {
541 assert!(TcpFlags::S.is_syn());
542 assert!(!TcpFlags::SA.is_syn()); assert!(TcpFlags::SA.is_syn_ack());
544 assert!(TcpFlags::A.is_ack());
545 assert!(TcpFlags::FA.is_fin());
546 assert!(TcpFlags::R.is_rst());
547 }
548
549 #[test]
550 fn test_bit_ops() {
551 let flags = TcpFlags::S | TcpFlags::A;
552 assert!(flags.syn);
553 assert!(flags.ack);
554
555 let flags = TcpFlags::SA & TcpFlags::S;
556 assert!(flags.syn);
557 assert!(!flags.ack);
558 }
559
560 #[test]
561 fn test_from_bytes() {
562 let flags = TcpFlags::from_bytes(0x50, 0x12);
566 assert!(flags.syn);
567 assert!(flags.ack);
568 assert!(!flags.ns);
569
570 let flags = TcpFlags::from_bytes(0x51, 0x12);
572 assert!(flags.syn);
573 assert!(flags.ack);
574 assert!(flags.ns);
575 }
576
577 #[test]
578 fn test_constants() {
579 assert_eq!(TcpFlags::NONE.to_u16(), 0);
580 assert_eq!(TcpFlags::S.to_u16(), 0x002);
581 assert_eq!(TcpFlags::SA.to_u16(), 0x012);
582 assert_eq!(TcpFlags::A.to_u16(), 0x010);
583 assert_eq!(TcpFlags::FA.to_u16(), 0x011);
584 assert_eq!(TcpFlags::R.to_u16(), 0x004);
585 assert_eq!(TcpFlags::RA.to_u16(), 0x014);
586 assert_eq!(TcpFlags::PA.to_u16(), 0x018);
587 }
588}