aya/programs/sk_skb.rs
1//! Skskb programs.
2
3use std::{os::fd::AsFd as _, path::Path};
4
5use crate::{
6 generated::{
7 bpf_attach_type::{BPF_SK_SKB_STREAM_PARSER, BPF_SK_SKB_STREAM_VERDICT},
8 bpf_prog_type::BPF_PROG_TYPE_SK_SKB,
9 },
10 maps::sock::SockMapFd,
11 programs::{
12 define_link_wrapper, load_program, CgroupAttachMode, ProgAttachLink, ProgAttachLinkId,
13 ProgramData, ProgramError,
14 },
15 VerifierLogLevel,
16};
17
18/// The kind of [`SkSkb`] program.
19#[derive(Copy, Clone, Debug)]
20pub enum SkSkbKind {
21 /// A Stream Parser
22 StreamParser,
23 /// A Stream Verdict
24 StreamVerdict,
25}
26
27/// A program used to intercept ingress socket buffers.
28///
29/// [`SkSkb`] programs are attached to [socket maps], and can be used to
30/// inspect, redirect or filter incoming packet. See also [`SockMap`] and
31/// [`SockHash`].
32///
33/// # Minimum kernel version
34///
35/// The minimum kernel version required to use this feature is 4.14.
36///
37/// # Examples
38///
39/// ```no_run
40/// # #[derive(Debug, thiserror::Error)]
41/// # enum Error {
42/// # #[error(transparent)]
43/// # IO(#[from] std::io::Error),
44/// # #[error(transparent)]
45/// # Map(#[from] aya::maps::MapError),
46/// # #[error(transparent)]
47/// # Program(#[from] aya::programs::ProgramError),
48/// # #[error(transparent)]
49/// # Ebpf(#[from] aya::EbpfError)
50/// # }
51/// # let mut bpf = aya::Ebpf::load(&[])?;
52/// use aya::maps::SockMap;
53/// use aya::programs::SkSkb;
54///
55/// let intercept_ingress: SockMap<_> = bpf.map("INTERCEPT_INGRESS").unwrap().try_into()?;
56/// let map_fd = intercept_ingress.fd().try_clone()?;
57///
58/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?;
59/// prog.load()?;
60/// prog.attach(&map_fd)?;
61///
62/// # Ok::<(), Error>(())
63/// ```
64///
65/// [socket maps]: crate::maps::sock
66/// [`SockMap`]: crate::maps::SockMap
67/// [`SockHash`]: crate::maps::SockHash
68#[derive(Debug)]
69#[doc(alias = "BPF_PROG_TYPE_SK_SKB")]
70pub struct SkSkb {
71 pub(crate) data: ProgramData<SkSkbLink>,
72 pub(crate) kind: SkSkbKind,
73}
74
75impl SkSkb {
76 /// Loads the program inside the kernel.
77 pub fn load(&mut self) -> Result<(), ProgramError> {
78 load_program(BPF_PROG_TYPE_SK_SKB, &mut self.data)
79 }
80
81 /// Attaches the program to the given socket map.
82 ///
83 /// The returned value can be used to detach, see [SkSkb::detach].
84 pub fn attach(&mut self, map: &SockMapFd) -> Result<SkSkbLinkId, ProgramError> {
85 let prog_fd = self.fd()?;
86 let prog_fd = prog_fd.as_fd();
87
88 let attach_type = match self.kind {
89 SkSkbKind::StreamParser => BPF_SK_SKB_STREAM_PARSER,
90 SkSkbKind::StreamVerdict => BPF_SK_SKB_STREAM_VERDICT,
91 };
92
93 let link =
94 ProgAttachLink::attach(prog_fd, map.as_fd(), attach_type, CgroupAttachMode::Single)?;
95
96 self.data.links.insert(SkSkbLink::new(link))
97 }
98
99 /// Detaches the program.
100 ///
101 /// See [SkSkb::attach].
102 pub fn detach(&mut self, link_id: SkSkbLinkId) -> Result<(), ProgramError> {
103 self.data.links.remove(link_id)
104 }
105
106 /// Takes ownership of the link referenced by the provided link_id.
107 ///
108 /// The link will be detached on `Drop` and the caller is now responsible
109 /// for managing its lifetime.
110 pub fn take_link(&mut self, link_id: SkSkbLinkId) -> Result<SkSkbLink, ProgramError> {
111 self.data.take_link(link_id)
112 }
113
114 /// Creates a program from a pinned entry on a bpffs.
115 ///
116 /// Existing links will not be populated. To work with existing links you should use [`crate::programs::links::PinnedLink`].
117 ///
118 /// On drop, any managed links are detached and the program is unloaded. This will not result in
119 /// the program being unloaded from the kernel if it is still pinned.
120 pub fn from_pin<P: AsRef<Path>>(path: P, kind: SkSkbKind) -> Result<Self, ProgramError> {
121 let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
122 Ok(Self { data, kind })
123 }
124}
125
126define_link_wrapper!(
127 /// The link used by [SkSkb] programs.
128 SkSkbLink,
129 /// The type returned by [SkSkb::attach]. Can be passed to [SkSkb::detach].
130 SkSkbLinkId,
131 ProgAttachLink,
132 ProgAttachLinkId
133);