#[allow(dead_code)]
#[repr(packed)]
pub struct RawUDPPacket {
version_ihl: u8, dscp_ecn: u8, total_length: u16, identification: u16, flags_fragment_offset: u16, ttl: u8, protocol: u8, ip_checksum: u16, source_addr: u32, dest_addr: u32,
source_port: u16, dest_port: u16, length: u16, udp_checksum: u16,
data: [u8; 546], }
impl RawUDPPacket {
pub fn as_bytes(&self) -> &[u8] {
unsafe { std::slice::from_raw_parts(self as *const Self as *const u8, 574) }
}
}
impl From<UDPPacket> for RawUDPPacket {
fn from(item: UDPPacket) -> Self {
let ph: PseudoHeader = item.clone().into();
let udp_checksum = ph.checksum();
let source_addr: u32 = item.source_addr.into();
let dest_addr: u32 = item.dest_addr.into();
let mut packet = Self {
version_ihl: 0x45, dscp_ecn: 0, total_length: 574_u16.to_be(), identification: 0x1337, flags_fragment_offset: 0,
ttl: 64, protocol: 17, ip_checksum: 0, source_addr: source_addr.to_be(),
dest_addr: dest_addr.to_be(),
source_port: item.source_port.to_be(),
dest_port: item.dest_port.to_be(),
length: ((item.data.len() + 8) as u16).to_be(),
udp_checksum: udp_checksum,
data: item.data,
};
let header_u16 =
unsafe { std::slice::from_raw_parts(&packet as *const Self as *const u16, 10) };
let mut total: u16 = 0;
for &word in header_u16 {
let (value, carry) = total.overflowing_add(word);
if carry {
total = value + 1;
} else {
total = value;
}
}
packet.ip_checksum = !total;
return packet;
}
}
#[allow(dead_code)]
#[repr(packed)]
struct PseudoHeader {
source_addr: u32,
dest_addr: u32,
zero: u8,
protocol: u8,
udp_length: u16,
source_port: u16,
dest_port: u16,
udp_length2: u16,
udp_checksum: u16,
data: [u8; 546],
}
impl From<UDPPacket> for PseudoHeader {
fn from(item: UDPPacket) -> Self {
let source_addr: u32 = item.source_addr.into();
let dest_addr: u32 = item.dest_addr.into();
Self {
source_addr: source_addr.to_be(),
dest_addr: dest_addr.to_be(),
zero: 0,
protocol: 17,
udp_length: ((item.data.len() + 8) as u16).to_be(),
source_port: item.source_port.to_be(),
dest_port: item.dest_port.to_be(),
udp_length2: ((item.data.len() + 8) as u16).to_be(),
udp_checksum: 0,
data: item.data,
}
}
}
impl PseudoHeader {
pub fn checksum(&self) -> u16 {
let as_u16 = unsafe {
std::slice::from_raw_parts(
self as *const Self as *const u16,
(self.data.len() + 20) / 2,
)
};
let mut total: u16 = 0;
for &word in as_u16 {
let (value, carry) = total.overflowing_add(word);
if carry {
total = value + 1;
} else {
total = value;
}
}
!total
}
}
#[derive(Clone)]
pub struct UDPPacket {
pub source_addr: std::net::Ipv4Addr,
pub dest_addr: std::net::Ipv4Addr,
pub source_port: u16,
pub dest_port: u16,
data: [u8; 546],
}
impl From<RawUDPPacket> for UDPPacket {
fn from(item: RawUDPPacket) -> Self {
Self {
source_addr: std::net::Ipv4Addr::from(item.source_addr.to_be_bytes()),
dest_addr: std::net::Ipv4Addr::from(item.source_addr.to_be_bytes()),
source_port: u16::from_be(item.source_port),
dest_port: u16::from_be(item.dest_port),
data: item.data,
}
}
}
impl UDPPacket {
pub fn new(
source_addr: std::net::Ipv4Addr,
dest_addr: std::net::Ipv4Addr,
source_port: u16,
dest_port: u16,
data: [u8; 546],
) -> Self {
Self {
source_addr: source_addr,
dest_addr: dest_addr,
source_port: source_port,
dest_port: dest_port,
data: data,
}
}
pub fn get_data(&self) -> &[u8] {
return &self.data;
}
}