s2n_quic_platform/bpf/
program.rs1use super::{instruction::Dialect, Instruction};
5use core::{fmt, mem::size_of};
6use libc::sock_fprog;
7use std::{io, os::fd::AsRawFd};
8
9pub struct Program<'a, D: Dialect> {
10 instructions: &'a [Instruction<D>],
11}
12
13impl<'a, D: Dialect> Program<'a, D> {
14 #[inline]
15 pub const fn new(instructions: &'a [Instruction<D>]) -> Self {
16 if instructions.len() > D::MAX_INSTRUCTIONS {
17 panic!("program too large");
18 }
19 Self { instructions }
20 }
21
22 #[inline]
23 pub fn attach<S: AsRawFd>(&self, socket: &S) -> io::Result<()> {
24 let prog = sock_fprog {
25 filter: self.instructions.as_ptr() as *const _ as *mut _,
26 len: self.instructions.len() as _,
27 };
28
29 let ret = unsafe {
30 libc::setsockopt(
31 socket.as_raw_fd(),
32 libc::SOL_SOCKET,
33 D::SOCKOPT as _,
34 &prog as *const _ as *const _,
35 size_of::<sock_fprog>() as _,
36 )
37 };
38
39 if ret < 0 {
40 Err(io::Error::last_os_error())
41 } else {
42 Ok(())
43 }
44 }
45}
46
47impl<D: Dialect> fmt::Debug for Program<'_, D> {
48 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49 f.debug_struct("Program")
50 .field("instructions", &self.instructions)
51 .finish()
52 }
53}
54
55impl<D: Dialect> fmt::Display for Program<'_, D> {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 for (idx, inst) in self.instructions.iter().enumerate() {
58 D::display(inst, f, Some(idx))?;
59 writeln!(f)?;
60 }
61 Ok(())
62 }
63}