use std::{os::fd::AsFd as _, path::Path};
use crate::{
generated::{
bpf_attach_type::{BPF_SK_SKB_STREAM_PARSER, BPF_SK_SKB_STREAM_VERDICT},
bpf_prog_type::BPF_PROG_TYPE_SK_SKB,
},
maps::sock::SockMapFd,
programs::{
define_link_wrapper, load_program, CgroupAttachMode, ProgAttachLink, ProgAttachLinkId,
ProgramData, ProgramError,
},
VerifierLogLevel,
};
#[derive(Copy, Clone, Debug)]
pub enum SkSkbKind {
StreamParser,
StreamVerdict,
}
#[derive(Debug)]
#[doc(alias = "BPF_PROG_TYPE_SK_SKB")]
pub struct SkSkb {
pub(crate) data: ProgramData<SkSkbLink>,
pub(crate) kind: SkSkbKind,
}
impl SkSkb {
pub fn load(&mut self) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_SK_SKB, &mut self.data)
}
pub fn attach(&mut self, map: &SockMapFd) -> Result<SkSkbLinkId, ProgramError> {
let prog_fd = self.fd()?;
let prog_fd = prog_fd.as_fd();
let attach_type = match self.kind {
SkSkbKind::StreamParser => BPF_SK_SKB_STREAM_PARSER,
SkSkbKind::StreamVerdict => BPF_SK_SKB_STREAM_VERDICT,
};
let link =
ProgAttachLink::attach(prog_fd, map.as_fd(), attach_type, CgroupAttachMode::Single)?;
self.data.links.insert(SkSkbLink::new(link))
}
pub fn detach(&mut self, link_id: SkSkbLinkId) -> Result<(), ProgramError> {
self.data.links.remove(link_id)
}
pub fn take_link(&mut self, link_id: SkSkbLinkId) -> Result<SkSkbLink, ProgramError> {
self.data.take_link(link_id)
}
pub fn from_pin<P: AsRef<Path>>(path: P, kind: SkSkbKind) -> Result<Self, ProgramError> {
let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
Ok(Self { data, kind })
}
}
define_link_wrapper!(
SkSkbLink,
SkSkbLinkId,
ProgAttachLink,
ProgAttachLinkId
);