use std::net::{Ipv4Addr, Ipv6Addr};
use crate::protocols::utils::IP_V6_HDR_LEN;
use anyhow::Context;
use pnet::packet::Packet;
use pnet::packet::ethernet::EthernetPacket;
use pnet::packet::ip::IpNextHeaderProtocol;
use pnet::packet::ipv4::Ipv4Packet;
use pnet::packet::ipv6::{Ipv6Packet, MutableIpv6Packet};
pub fn create_ipv6_header(
src_addr: Ipv6Addr,
dst_addr: Ipv6Addr,
payload_length: u16,
next_protocol: IpNextHeaderProtocol,
) -> anyhow::Result<Vec<u8>> {
let mut buffer: [u8; IP_V6_HDR_LEN] = [0; IP_V6_HDR_LEN];
{
let mut ipv6: MutableIpv6Packet =
MutableIpv6Packet::new(&mut buffer[..]).context("creating ipv6 packet")?;
ipv6.set_version(6);
ipv6.set_traffic_class(0);
ipv6.set_flow_label(rand::random());
ipv6.set_payload_length(payload_length);
ipv6.set_next_header(next_protocol);
ipv6.set_hop_limit(1);
ipv6.set_source(src_addr);
ipv6.set_destination(dst_addr);
}
Ok(buffer.to_vec())
}
pub fn get_ipv6_src_addr_from_eth(frame: &EthernetPacket) -> anyhow::Result<Ipv6Addr> {
let ipv6_packet: Ipv6Packet = Ipv6Packet::new(frame.payload()).context(format!(
"truncated or invalid ipv6 packet (payload len {})",
frame.payload().len()
))?;
Ok(ipv6_packet.get_source())
}
pub fn get_ipv6_dst_addr_from_eth(frame: &EthernetPacket) -> anyhow::Result<Ipv6Addr> {
let ipv6_packet: Ipv6Packet = Ipv6Packet::new(frame.payload()).context(format!(
"truncated or invalid ipv6 packet (payload len {})",
frame.payload().len()
))?;
Ok(ipv6_packet.get_destination())
}
pub fn get_ipv4_addr_from_eth(frame: &EthernetPacket) -> anyhow::Result<Ipv4Addr> {
let ipv4_packet: Ipv4Packet = Ipv4Packet::new(frame.payload()).context(format!(
"truncated or invalid ipv4 packet (payload len {})",
frame.payload().len()
))?;
Ok(ipv4_packet.get_source())
}