memmove_test.rs 1.3 KB

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