use core::{
borrow::{Borrow, BorrowMut},
marker::PhantomData,
ptr,
};
use crate::{
ENOENT, EbpfContext as _,
bindings::{bpf_map_type::BPF_MAP_TYPE_SOCKHASH, bpf_sock_ops},
cty::c_long,
helpers::{
bpf_msg_redirect_hash, bpf_sk_assign, bpf_sk_redirect_hash, bpf_sk_release,
bpf_sock_hash_update,
},
lookup,
maps::{MapDef, PinningType},
programs::{SkBuffContext, SkLookupContext, SkMsgContext},
};
#[repr(transparent)]
pub struct SockHash<K> {
def: MapDef,
_k: PhantomData<K>,
}
impl<K> super::private::Map for SockHash<K> {
type Key = K;
type Value = u32;
}
impl<K> SockHash<K> {
map_constructors!(K, u32, BPF_MAP_TYPE_SOCKHASH, phantom _k);
pub fn update(
&self,
mut key: impl BorrowMut<K>,
mut sk_ops: impl BorrowMut<bpf_sock_ops>,
flags: u64,
) -> Result<(), i32> {
let ret = unsafe {
bpf_sock_hash_update(
ptr::from_mut(sk_ops.borrow_mut()),
self.def.as_ptr().cast(),
ptr::from_mut(key.borrow_mut()).cast(),
flags,
)
};
(ret == 0).then_some(()).ok_or(ret as i32)
}
pub fn redirect_msg(
&self,
ctx: impl Borrow<SkMsgContext>,
mut key: impl BorrowMut<K>,
flags: u64,
) -> c_long {
unsafe {
bpf_msg_redirect_hash(
ctx.borrow().msg,
self.def.as_ptr().cast(),
ptr::from_mut(key.borrow_mut()).cast(),
flags,
)
}
}
pub fn redirect_skb(
&self,
ctx: impl Borrow<SkBuffContext>,
mut key: impl BorrowMut<K>,
flags: u64,
) -> c_long {
unsafe {
bpf_sk_redirect_hash(
ctx.borrow().skb.skb,
self.def.as_ptr().cast(),
ptr::from_mut(key.borrow_mut()).cast(),
flags,
)
}
}
pub fn redirect_sk_lookup(
&self,
ctx: impl Borrow<SkLookupContext>,
key: impl Borrow<K>,
flags: u64,
) -> Result<(), i32> {
let sk = lookup(self.def.as_ptr(), key.borrow()).ok_or(-ENOENT)?;
let ret = unsafe { bpf_sk_assign(ctx.borrow().as_ptr().cast(), sk.as_ptr(), flags) };
let _: c_long = unsafe { bpf_sk_release(sk.as_ptr()) };
(ret == 0).then_some(()).ok_or(ret as i32)
}
}