123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 |
- #![no_std]
- #![no_main]
- use core::mem;
- use aya_ebpf::{
- bindings::{BPF_F_NO_PREALLOC, xdp_action},
- macros::{map, xdp},
- maps::HashMap,
- programs::XdpContext,
- };
- #[cfg(not(test))]
- extern crate ebpf_panic;
- use network_types::{
- eth::{EthHdr, EtherType},
- ip::Ipv6Hdr,
- };
- #[inline(always)]
- fn ptr_at<T>(ctx: &XdpContext, offset: usize) -> Result<*const T, ()> {
- let start = ctx.data();
- let end = ctx.data_end();
- let len = mem::size_of::<T>();
- if start + offset + len > end {
- return Err(());
- }
- Ok((start + offset) as *const T)
- }
- struct Value {
- pub orig_ip: [u8; 16],
- }
- #[map]
- static RULES: HashMap<u8, Value> = HashMap::<u8, Value>::with_max_entries(1, BPF_F_NO_PREALLOC);
- #[xdp]
- pub fn do_dnat(ctx: XdpContext) -> u32 {
- try_do_dnat(ctx).unwrap_or(xdp_action::XDP_DROP)
- }
- fn try_do_dnat(ctx: XdpContext) -> Result<u32, ()> {
- let index = 0;
- if let Some(nat) = unsafe { RULES.get(&index) } {
- let hproto: *const EtherType = ptr_at(&ctx, mem::offset_of!(EthHdr, ether_type))?;
- match unsafe { *hproto } {
- EtherType::Ipv6 => {
- let ip_hdr: *const Ipv6Hdr = ptr_at(&ctx, EthHdr::LEN)?;
- unsafe { (*ip_hdr.cast_mut()).dst_addr = nat.orig_ip };
- }
- _ => return Ok(xdp_action::XDP_PASS),
- }
- }
- Ok(xdp_action::XDP_PASS)
- }
|