use std::net::{Ipv4Addr, SocketAddrV4};
use smoltcp::phy::ChecksumCapabilities;
use smoltcp::wire::{IpAddress, IpProtocol, Ipv4Packet, Ipv4Repr, UdpPacket, UdpRepr};
pub fn build_ipv4_udp(src: SocketAddrV4, dst: SocketAddrV4, payload: &[u8]) -> Vec<u8> {
let udp_repr = UdpRepr {
src_port: src.port(),
dst_port: dst.port(),
};
let ip_repr = Ipv4Repr {
src_addr: *src.ip(),
dst_addr: *dst.ip(),
next_header: IpProtocol::Udp,
payload_len: udp_repr.header_len() + payload.len(),
hop_limit: 64,
};
let mut buf = vec![0u8; ip_repr.buffer_len() + ip_repr.payload_len];
let mut ip_pkt = Ipv4Packet::new_unchecked(&mut buf);
ip_repr.emit(&mut ip_pkt, &ChecksumCapabilities::default());
let mut udp_pkt = UdpPacket::new_unchecked(ip_pkt.payload_mut());
udp_repr.emit(
&mut udp_pkt,
&IpAddress::Ipv4(*src.ip()),
&IpAddress::Ipv4(*dst.ip()),
payload.len(),
|b| b.copy_from_slice(payload),
&ChecksumCapabilities::default(),
);
buf
}
pub struct ParsedUdp {
pub src: SocketAddrV4,
pub payload: Vec<u8>,
}
pub fn parse_ipv4_udp(bytes: &[u8]) -> Option<ParsedUdp> {
let ip_pkt = Ipv4Packet::new_checked(bytes).ok()?;
if ip_pkt.next_header() != IpProtocol::Udp {
return None;
}
let src_ip: Ipv4Addr = ip_pkt.src_addr();
let udp_pkt = UdpPacket::new_checked(ip_pkt.payload()).ok()?;
Some(ParsedUdp {
src: SocketAddrV4::new(src_ip, udp_pkt.src_port()),
payload: udp_pkt.payload().to_vec(),
})
}