|
| 1 | +use crate::net::parser::raw::protocols::ProtocolParser; |
| 2 | +use crate::net::parser::raw::RawProtocolHeader; |
| 3 | + |
| 4 | +pub struct IcmpParser; |
| 5 | + |
| 6 | +impl ProtocolParser for IcmpParser { |
| 7 | + fn protocol_number() -> u8 { |
| 8 | + 1 // ICMP protocol number |
| 9 | + } |
| 10 | + |
| 11 | + fn parse_packet(payload: &[u8], _protocol_number: u8) -> Option<RawProtocolHeader> { |
| 12 | + // ICMP header format: |
| 13 | + // 0 1 2 3 |
| 14 | + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| 15 | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 16 | + // | Type | Code | Checksum | |
| 17 | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 18 | + // | Data | |
| 19 | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 20 | + |
| 21 | + if payload.len() < 4 { |
| 22 | + return None; |
| 23 | + } |
| 24 | + |
| 25 | + let icmp_type = payload[0]; |
| 26 | + let icmp_code = payload[1]; |
| 27 | + // Checksum is at payload[2..4] but we don't validate it here |
| 28 | + |
| 29 | + Some( |
| 30 | + RawProtocolHeader::new( |
| 31 | + None, |
| 32 | + None, |
| 33 | + icmp_type as u16, // Using type as src_port |
| 34 | + icmp_code as u16, // Using code as dst_port |
| 35 | + Self::protocol_number(), |
| 36 | + payload.len() as u16, |
| 37 | + if payload.len() > 4 { |
| 38 | + Some(payload[4..].to_vec()) |
| 39 | + } else { |
| 40 | + None |
| 41 | + }, |
| 42 | + ) |
| 43 | + .with_raw_packet(payload.to_vec()) |
| 44 | + .with_flags(icmp_type) |
| 45 | + .with_version(icmp_code), |
| 46 | + ) |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +#[cfg(test)] |
| 51 | +mod tests { |
| 52 | + use super::*; |
| 53 | + |
| 54 | + #[test] |
| 55 | + fn test_icmp_parser() { |
| 56 | + // Echo request (ping) packet |
| 57 | + let payload = &[ |
| 58 | + 8, // Type: Echo request |
| 59 | + 0, // Code: 0 |
| 60 | + 0x00, 0x00, // Checksum (not validated in this test) |
| 61 | + 0x12, 0x34, // Identifier |
| 62 | + 0x56, 0x78, // Sequence number |
| 63 | + ]; |
| 64 | + |
| 65 | + let result = IcmpParser::parse_packet(payload, IcmpParser::protocol_number()); |
| 66 | + assert!(result.is_some()); |
| 67 | + |
| 68 | + let header = result.unwrap(); |
| 69 | + assert_eq!(header.src_port, 8); // Echo request type |
| 70 | + assert_eq!(header.dst_port, 0); // Code 0 |
| 71 | + assert_eq!(header.protocol, 1); // ICMP protocol |
| 72 | + assert_eq!(header.length, payload.len() as u16); |
| 73 | + } |
| 74 | +} |
0 commit comments