Skip to main content

zond_engine/protocols/
ip.rs

1// Copyright (c) 2026 Erik Lening (hollowpointer) and Contributors
2//
3// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
4// If a copy of the MPL was not distributed with this file, You can obtain one at
5// https://mozilla.org/MPL/2.0/.
6
7use std::net::{Ipv4Addr, Ipv6Addr};
8
9use crate::protocols::utils::IP_V6_HDR_LEN;
10use anyhow::Context;
11use pnet::packet::Packet;
12use pnet::packet::ethernet::EthernetPacket;
13use pnet::packet::ip::IpNextHeaderProtocol;
14use pnet::packet::ipv4::Ipv4Packet;
15use pnet::packet::ipv6::{Ipv6Packet, MutableIpv6Packet};
16
17// const WORD_LEN: usize = 4;
18// const NO_FRAG_FLAG: u8 = 1 << 1;
19
20// pub fn create_ipv4_header(
21//     src_addr: Ipv4Addr,
22//     dst_addr: Ipv4Addr,
23//     total_length: u16,
24//     next_protocol: IpNextHeaderProtocol,
25// ) -> anyhow::Result<Vec<u8>> {
26//     let mut buffer: [u8; IP_V4_HDR_LEN] = [0; IP_V4_HDR_LEN];
27//     {
28//         let mut ipv4: MutableIpv4Packet = MutableIpv4Packet::new(&mut buffer[..])
29//             .context("creating ipv4 packet")?;
30//         ipv4.set_version(4);
31//         ipv4.set_header_length((IP_V4_HDR_LEN / WORD_LEN) as u8);
32//         ipv4.set_dscp(0);
33//         ipv4.set_ecn(0);
34//         ipv4.set_total_length(total_length);
35//         ipv4.set_identification(rand::random());
36//         ipv4.set_flags(NO_FRAG_FLAG);
37//         ipv4.set_fragment_offset(0);
38//         ipv4.set_ttl(64);
39//         ipv4.set_next_level_protocol(next_protocol);
40//         ipv4.set_source(src_addr);
41//         ipv4.set_destination(dst_addr);
42//         let ipv4_imm = ipv4.to_immutable();
43//         let ipv4_pkt = Ipv4Packet::new(ipv4_imm.packet()).context("transforming ipv4 to packet")?;
44//         let csm = checksum(&ipv4_pkt);
45//         ipv4.set_checksum(csm);
46//     }
47
48//     Ok(buffer.to_vec())
49// }
50
51pub fn create_ipv6_header(
52    src_addr: Ipv6Addr,
53    dst_addr: Ipv6Addr,
54    payload_length: u16,
55    next_protocol: IpNextHeaderProtocol,
56) -> anyhow::Result<Vec<u8>> {
57    let mut buffer: [u8; IP_V6_HDR_LEN] = [0; IP_V6_HDR_LEN];
58    {
59        let mut ipv6: MutableIpv6Packet =
60            MutableIpv6Packet::new(&mut buffer[..]).context("creating ipv6 packet")?;
61        ipv6.set_version(6);
62        ipv6.set_traffic_class(0);
63        ipv6.set_flow_label(rand::random());
64        ipv6.set_payload_length(payload_length);
65        ipv6.set_next_header(next_protocol);
66        ipv6.set_hop_limit(1);
67        ipv6.set_source(src_addr);
68        ipv6.set_destination(dst_addr);
69    }
70    Ok(buffer.to_vec())
71}
72
73pub fn get_ipv6_src_addr_from_eth(frame: &EthernetPacket) -> anyhow::Result<Ipv6Addr> {
74    let ipv6_packet: Ipv6Packet = Ipv6Packet::new(frame.payload()).context(format!(
75        "truncated or invalid ipv6 packet (payload len {})",
76        frame.payload().len()
77    ))?;
78    Ok(ipv6_packet.get_source())
79}
80
81pub fn get_ipv6_dst_addr_from_eth(frame: &EthernetPacket) -> anyhow::Result<Ipv6Addr> {
82    let ipv6_packet: Ipv6Packet = Ipv6Packet::new(frame.payload()).context(format!(
83        "truncated or invalid ipv6 packet (payload len {})",
84        frame.payload().len()
85    ))?;
86    Ok(ipv6_packet.get_destination())
87}
88
89pub fn get_ipv4_addr_from_eth(frame: &EthernetPacket) -> anyhow::Result<Ipv4Addr> {
90    let ipv4_packet: Ipv4Packet = Ipv4Packet::new(frame.payload()).context(format!(
91        "truncated or invalid ipv4 packet (payload len {})",
92        frame.payload().len()
93    ))?;
94    Ok(ipv4_packet.get_source())
95}