aya-ebpf 0.2.1

A library for writing eBPF programs
Documentation
use crate::{
    ENOENT, EbpfContext as _,
    bindings::{bpf_map_type::BPF_MAP_TYPE_SOCKMAP, bpf_sock_ops},
    cty::c_long,
    helpers::{
        bpf_msg_redirect_map, bpf_sk_assign, bpf_sk_redirect_map, bpf_sk_release,
        bpf_sock_map_update,
    },
    lookup,
    maps::{MapDef, PinningType},
    programs::{SkBuffContext, SkLookupContext, SkMsgContext},
};

#[repr(transparent)]
pub struct SockMap {
    def: MapDef,
}

impl super::private::Map for SockMap {
    type Key = u32;
    type Value = u32;
}

impl SockMap {
    map_constructors!(u32, u32, BPF_MAP_TYPE_SOCKMAP);

    #[expect(clippy::missing_safety_doc, reason = "TODO")]
    pub unsafe fn update(
        &self,
        mut index: u32,
        sk_ops: *mut bpf_sock_ops,
        flags: u64,
    ) -> Result<(), i32> {
        let ret = unsafe {
            bpf_sock_map_update(
                sk_ops,
                self.def.as_ptr().cast(),
                core::ptr::from_mut(&mut index).cast(),
                flags,
            )
        };
        if ret == 0 { Ok(()) } else { Err(ret as i32) }
    }

    #[expect(clippy::missing_safety_doc, reason = "TODO")]
    pub unsafe fn redirect_msg(&self, ctx: &SkMsgContext, index: u32, flags: u64) -> c_long {
        unsafe { bpf_msg_redirect_map(ctx.as_ptr().cast(), self.def.as_ptr().cast(), index, flags) }
    }

    #[expect(clippy::missing_safety_doc, reason = "TODO")]
    pub unsafe fn redirect_skb(&self, ctx: &SkBuffContext, index: u32, flags: u64) -> c_long {
        unsafe { bpf_sk_redirect_map(ctx.as_ptr().cast(), self.def.as_ptr().cast(), index, flags) }
    }

    pub fn redirect_sk_lookup(
        &self,
        ctx: &SkLookupContext,
        index: u32,
        flags: u64,
    ) -> Result<(), i32> {
        let sk = lookup(self.def.as_ptr(), &index).ok_or(-ENOENT)?;
        let ret = unsafe { bpf_sk_assign(ctx.as_ptr().cast(), sk.as_ptr(), flags) };
        let _: c_long = unsafe { bpf_sk_release(sk.as_ptr()) };
        if ret == 0 { Ok(()) } else { Err(ret as i32) }
    }
}