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) }
}
}