|
|
|
@ -109,8 +109,8 @@ use crate::{
|
|
|
|
|
pin::PinError,
|
|
|
|
|
sys::{
|
|
|
|
|
bpf_btf_get_fd_by_id, bpf_get_object, bpf_load_program, bpf_pin_object,
|
|
|
|
|
bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd, bpf_prog_query, retry_with_verifier_logs,
|
|
|
|
|
BpfLoadProgramAttrs,
|
|
|
|
|
bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd, bpf_prog_get_next_id, bpf_prog_query,
|
|
|
|
|
retry_with_verifier_logs, BpfLoadProgramAttrs,
|
|
|
|
|
},
|
|
|
|
|
util::VerifierLog,
|
|
|
|
|
};
|
|
|
|
@ -912,6 +912,7 @@ impl_try_from_program!(
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/// Provides information about a loaded program, like name, id and statistics
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct ProgramInfo(bpf_prog_info);
|
|
|
|
|
|
|
|
|
|
impl ProgramInfo {
|
|
|
|
@ -971,3 +972,81 @@ impl ProgramInfo {
|
|
|
|
|
Ok(ProgramInfo(info))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// ProgramsIter is an Iterator over loaded eBPF programs.
|
|
|
|
|
pub struct ProgramsIter {
|
|
|
|
|
current: u32,
|
|
|
|
|
error: bool,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Iterator for ProgramsIter {
|
|
|
|
|
type Item = Result<ProgramInfo, ProgramError>;
|
|
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
|
if self.error {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
let current = self.current;
|
|
|
|
|
|
|
|
|
|
match bpf_prog_get_next_id(current) {
|
|
|
|
|
Ok(Some(next)) => {
|
|
|
|
|
self.current = next;
|
|
|
|
|
Some(
|
|
|
|
|
bpf_prog_get_fd_by_id(next)
|
|
|
|
|
.map_err(|io_error| ProgramError::SyscallError {
|
|
|
|
|
call: "bpf_prog_get_fd_by_id".to_owned(),
|
|
|
|
|
io_error,
|
|
|
|
|
})
|
|
|
|
|
.and_then(|fd| {
|
|
|
|
|
bpf_prog_get_info_by_fd(fd)
|
|
|
|
|
.map_err(|io_error| ProgramError::SyscallError {
|
|
|
|
|
call: "bpf_prog_get_info_by_fd".to_owned(),
|
|
|
|
|
io_error,
|
|
|
|
|
})
|
|
|
|
|
.map(ProgramInfo)
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
Ok(None) => None,
|
|
|
|
|
Err((_, io_error)) => {
|
|
|
|
|
// If getting the next program failed, we have to yield None in our next
|
|
|
|
|
// iteration to avoid an infinite loop.
|
|
|
|
|
self.error = true;
|
|
|
|
|
Some(Err(ProgramError::SyscallError {
|
|
|
|
|
call: "bpf_prog_get_fd_by_id".to_owned(),
|
|
|
|
|
io_error,
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns an iterator over all loaded bpf programs.
|
|
|
|
|
///
|
|
|
|
|
/// This differs from [`crate::Bpf::programs`] since it will return all programs
|
|
|
|
|
/// listed on the host system and not only programs a specific [`crate::Bpf`] instance.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # use aya::programs::loaded_programs;
|
|
|
|
|
///
|
|
|
|
|
/// for p in loaded_programs() {
|
|
|
|
|
/// match p {
|
|
|
|
|
/// Ok(program) => println!("{}", String::from_utf8_lossy(program.name())),
|
|
|
|
|
/// Err(e) => println!("Error iterating programs: {:?}", e),
|
|
|
|
|
/// }
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// Returns [`ProgramError::SyscallError`] if any of the syscalls required to either get
|
|
|
|
|
/// next program id, get the program fd, or the [`ProgramInfo`] fail. In cases where
|
|
|
|
|
/// iteration can't be performed, for example the caller does not have the necessary privileges,
|
|
|
|
|
/// a single item will be yielded containing the error that occurred.
|
|
|
|
|
pub fn loaded_programs() -> ProgramsIter {
|
|
|
|
|
ProgramsIter {
|
|
|
|
|
current: 0,
|
|
|
|
|
error: false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|