memmove_test.rs 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. #![no_std]
  2. #![no_main]
  3. #![expect(unused_crate_dependencies, reason = "used in other bins")]
  4. use core::mem;
  5. use aya_ebpf::{
  6. bindings::{BPF_F_NO_PREALLOC, xdp_action},
  7. macros::{map, xdp},
  8. maps::HashMap,
  9. programs::XdpContext,
  10. };
  11. #[cfg(not(test))]
  12. extern crate ebpf_panic;
  13. use network_types::{
  14. eth::{EthHdr, EtherType},
  15. ip::Ipv6Hdr,
  16. };
  17. #[inline(always)]
  18. fn ptr_at<T>(ctx: &XdpContext, offset: usize) -> Result<*const T, ()> {
  19. let start = ctx.data();
  20. let end = ctx.data_end();
  21. let len = mem::size_of::<T>();
  22. if start + offset + len > end {
  23. return Err(());
  24. }
  25. Ok((start + offset) as *const T)
  26. }
  27. struct Value {
  28. pub orig_ip: [u8; 16],
  29. }
  30. #[map]
  31. static RULES: HashMap<u8, Value> = HashMap::<u8, Value>::with_max_entries(1, BPF_F_NO_PREALLOC);
  32. #[xdp]
  33. fn do_dnat(ctx: XdpContext) -> u32 {
  34. try_do_dnat(ctx).unwrap_or(xdp_action::XDP_DROP)
  35. }
  36. fn try_do_dnat(ctx: XdpContext) -> Result<u32, ()> {
  37. let index = 0;
  38. if let Some(nat) = unsafe { RULES.get(index) } {
  39. let hproto: *const EtherType = ptr_at(&ctx, mem::offset_of!(EthHdr, ether_type))?;
  40. match unsafe { *hproto } {
  41. EtherType::Ipv6 => {
  42. let ip_hdr: *const Ipv6Hdr = ptr_at(&ctx, EthHdr::LEN)?;
  43. unsafe { (*ip_hdr.cast_mut()).dst_addr = nat.orig_ip };
  44. }
  45. _ => return Ok(xdp_action::XDP_PASS),
  46. }
  47. }
  48. Ok(xdp_action::XDP_PASS)
  49. }