socket_filter.rs 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. use libc::{setsockopt, SOL_SOCKET, SO_ATTACH_BPF, SO_DETACH_BPF};
  2. use std::{cell::RefCell, io, mem, os::unix::prelude::RawFd, rc::Rc};
  3. use crate::{
  4. generated::bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER,
  5. programs::{load_program, Link, LinkRef, ProgramData, ProgramError},
  6. };
  7. #[derive(Debug)]
  8. pub struct SocketFilter {
  9. pub(crate) data: ProgramData,
  10. }
  11. impl SocketFilter {
  12. pub fn load(&mut self) -> Result<(), ProgramError> {
  13. load_program(BPF_PROG_TYPE_SOCKET_FILTER, &mut self.data)
  14. }
  15. pub fn attach(&self, socket: RawFd) -> Result<impl Link, ProgramError> {
  16. let prog_fd = self.data.fd_or_err()?;
  17. let ret = unsafe {
  18. setsockopt(
  19. socket,
  20. SOL_SOCKET,
  21. SO_ATTACH_BPF,
  22. &prog_fd as *const _ as *const _,
  23. mem::size_of::<RawFd>() as u32,
  24. )
  25. };
  26. if ret < 0 {
  27. return Err(ProgramError::SocketFilterError {
  28. io_error: io::Error::last_os_error(),
  29. });
  30. }
  31. let link = Rc::new(RefCell::new(SocketFilterLink {
  32. socket,
  33. prog_fd: Some(prog_fd),
  34. }));
  35. Ok(LinkRef::new(&link))
  36. }
  37. }
  38. #[derive(Debug)]
  39. pub(crate) struct SocketFilterLink {
  40. socket: RawFd,
  41. prog_fd: Option<RawFd>,
  42. }
  43. impl Link for SocketFilterLink {
  44. fn detach(&mut self) -> Result<(), ProgramError> {
  45. if let Some(fd) = self.prog_fd.take() {
  46. unsafe {
  47. setsockopt(
  48. self.socket,
  49. SOL_SOCKET,
  50. SO_DETACH_BPF,
  51. &fd as *const _ as *const _,
  52. mem::size_of::<RawFd>() as u32,
  53. );
  54. }
  55. Ok(())
  56. } else {
  57. Err(ProgramError::AlreadyDetached)
  58. }
  59. }
  60. }
  61. impl Drop for SocketFilterLink {
  62. fn drop(&mut self) {
  63. let _ = self.detach();
  64. }
  65. }