1use std::ffi::c_void;
14use std::ffi::CStr;
15use std::ffi::OsStr;
16use std::ffi::OsString;
17use std::io;
18use std::mem::size_of_val;
19use std::mem::zeroed;
20use std::os::fd::AsFd;
21use std::os::fd::AsRawFd;
22use std::os::fd::BorrowedFd;
23use std::os::fd::FromRawFd;
24use std::os::fd::OwnedFd;
25use std::os::raw::c_char;
26use std::os::unix::ffi::OsStrExt;
27use std::path::PathBuf;
28use std::ptr;
29use std::time::Duration;
30
31use crate::util;
32use crate::CgroupIterOrder;
33use crate::MapType;
34use crate::ProgramAttachType;
35use crate::ProgramType;
36use crate::Result;
37
38fn cstr_to_os_string(s: &CStr) -> OsString {
40 OsStr::from_bytes(s.to_bytes()).to_owned()
41}
42
43macro_rules! gen_info_impl {
44 ($(#[$attr:meta])*
46 $name:ident, $info_ty:ty, $uapi_info_ty:ty, $next_id:expr, $fd_by_id:expr) => {
47 $(#[$attr])*
48 #[derive(Default, Debug)]
49 pub struct $name {
50 cur_id: u32,
51 }
52
53 impl $name {
54 fn next_valid_fd(&mut self) -> Option<OwnedFd> {
56 loop {
57 if unsafe { $next_id(self.cur_id, &mut self.cur_id) } != 0 {
58 return None;
59 }
60
61 let fd = unsafe { $fd_by_id(self.cur_id) };
62 if fd < 0 {
63 let err = io::Error::last_os_error();
64 if err.kind() == io::ErrorKind::NotFound {
65 continue;
66 }
67
68 return None;
69 }
70
71 return Some(unsafe { OwnedFd::from_raw_fd(fd)});
72 }
73 }
74 }
75
76 impl Iterator for $name {
77 type Item = $info_ty;
78
79 fn next(&mut self) -> Option<Self::Item> {
80 let fd = self.next_valid_fd()?;
81
82 let mut item: $uapi_info_ty = unsafe { std::mem::zeroed() };
88 let item_ptr: *mut $uapi_info_ty = &mut item;
89 let mut len = size_of_val(&item) as u32;
90
91 let ret = unsafe { libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr.cast(), &mut len) };
92 let parsed_uapi = if ret != 0 {
93 None
94 } else {
95 <$info_ty>::from_uapi(fd.as_fd(), item)
96 };
97
98 parsed_uapi
99 }
100 }
101 };
102}
103
104#[derive(Clone, Debug)]
106#[doc(alias = "bpf_line_info")]
107pub struct LineInfo {
108 pub insn_off: u32,
110 pub file_name_off: u32,
112 pub line_off: u32,
114 pub line_num: u32,
116 pub line_col: u32,
118}
119
120impl From<&libbpf_sys::bpf_line_info> for LineInfo {
121 fn from(item: &libbpf_sys::bpf_line_info) -> Self {
122 Self {
123 insn_off: item.insn_off,
124 file_name_off: item.file_name_off,
125 line_off: item.line_off,
126 line_num: item.line_col >> 10,
127 line_col: item.line_col & 0x3ff,
128 }
129 }
130}
131
132#[derive(Debug, Clone, Default)]
134#[repr(C)]
135pub struct Tag(pub [u8; 8]);
136
137#[derive(Debug, Clone)]
139#[doc(alias = "bpf_prog_info")]
140pub struct ProgramInfo {
141 pub name: OsString,
143 pub ty: ProgramType,
145 pub tag: Tag,
148 pub id: u32,
150 pub jited_prog_insns: Vec<u8>,
152 pub xlated_prog_insns: Vec<u8>,
154 pub load_time: Duration,
156 pub created_by_uid: u32,
158 pub map_ids: Vec<u32>,
160 pub ifindex: u32,
162 pub gpl_compatible: bool,
164 pub netns_dev: u64,
166 pub netns_ino: u64,
168 pub jited_ksyms: Vec<*const c_void>,
170 pub jited_func_lens: Vec<u32>,
172 pub btf_id: u32,
174 pub func_info_rec_size: u32,
176 pub func_info: Vec<libbpf_sys::bpf_func_info>,
178 pub line_info: Vec<LineInfo>,
180 pub jited_line_info: Vec<*const c_void>,
182 pub line_info_rec_size: u32,
184 pub jited_line_info_rec_size: u32,
186 pub prog_tags: Vec<Tag>,
188 pub run_time_ns: u64,
190 pub run_cnt: u64,
192 pub recursion_misses: u64,
194 pub verified_insns: u32,
196 #[doc(hidden)]
198 pub _non_exhaustive: (),
199}
200
201#[derive(Default, Debug)]
203#[doc(alias = "bpf_prog_get_next_id")]
204pub struct ProgInfoIter {
205 cur_id: u32,
206 opts: ProgInfoQueryOptions,
207}
208
209#[derive(Clone, Default, Debug)]
211pub struct ProgInfoQueryOptions {
212 include_xlated_prog_insns: bool,
214 include_jited_prog_insns: bool,
216 include_map_ids: bool,
218 include_line_info: bool,
220 include_func_info: bool,
222 include_jited_line_info: bool,
224 include_jited_func_lens: bool,
226 include_prog_tags: bool,
228 include_jited_ksyms: bool,
230}
231
232impl ProgInfoIter {
233 pub fn with_query_opts(opts: ProgInfoQueryOptions) -> Self {
235 Self {
236 opts,
237 ..Self::default()
238 }
239 }
240}
241
242impl ProgInfoQueryOptions {
243 pub fn include_xlated_prog_insns(mut self, v: bool) -> Self {
245 self.include_xlated_prog_insns = v;
246 self
247 }
248
249 pub fn include_jited_prog_insns(mut self, v: bool) -> Self {
251 self.include_jited_prog_insns = v;
252 self
253 }
254
255 pub fn include_map_ids(mut self, v: bool) -> Self {
257 self.include_map_ids = v;
258 self
259 }
260
261 pub fn include_line_info(mut self, v: bool) -> Self {
263 self.include_line_info = v;
264 self
265 }
266
267 pub fn include_func_info(mut self, v: bool) -> Self {
269 self.include_func_info = v;
270 self
271 }
272
273 pub fn include_jited_line_info(mut self, v: bool) -> Self {
275 self.include_jited_line_info = v;
276 self
277 }
278
279 pub fn include_jited_func_lens(mut self, v: bool) -> Self {
281 self.include_jited_func_lens = v;
282 self
283 }
284
285 pub fn include_prog_tags(mut self, v: bool) -> Self {
287 self.include_prog_tags = v;
288 self
289 }
290
291 pub fn include_jited_ksyms(mut self, v: bool) -> Self {
293 self.include_jited_ksyms = v;
294 self
295 }
296
297 pub fn include_all(self) -> Self {
299 Self {
300 include_xlated_prog_insns: true,
301 include_jited_prog_insns: true,
302 include_map_ids: true,
303 include_line_info: true,
304 include_func_info: true,
305 include_jited_line_info: true,
306 include_jited_func_lens: true,
307 include_prog_tags: true,
308 include_jited_ksyms: true,
309 }
310 }
311}
312
313impl ProgramInfo {
314 fn load_from_fd(fd: BorrowedFd<'_>, opts: &ProgInfoQueryOptions) -> Result<Self> {
315 let mut item = libbpf_sys::bpf_prog_info::default();
316
317 let mut xlated_prog_insns: Vec<u8> = Vec::new();
318 let mut jited_prog_insns: Vec<u8> = Vec::new();
319 let mut map_ids: Vec<u32> = Vec::new();
320 let mut jited_line_info: Vec<*const c_void> = Vec::new();
321 let mut line_info: Vec<libbpf_sys::bpf_line_info> = Vec::new();
322 let mut func_info: Vec<libbpf_sys::bpf_func_info> = Vec::new();
323 let mut jited_func_lens: Vec<u32> = Vec::new();
324 let mut prog_tags: Vec<Tag> = Vec::new();
325 let mut jited_ksyms: Vec<*const c_void> = Vec::new();
326
327 let item_ptr: *mut libbpf_sys::bpf_prog_info = &mut item;
328 let mut len = size_of_val(&item) as u32;
329
330 let ret = unsafe {
331 libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr.cast::<c_void>(), &mut len)
332 };
333 util::parse_ret(ret)?;
334
335 let name = util::c_char_slice_to_cstr(&item.name).unwrap();
337 let ty = ProgramType::from(item.type_);
338
339 if opts.include_xlated_prog_insns {
340 xlated_prog_insns.resize(item.xlated_prog_len as usize, 0u8);
341 item.xlated_prog_insns = xlated_prog_insns.as_mut_ptr().cast::<c_void>() as u64;
342 } else {
343 item.xlated_prog_len = 0;
344 }
345
346 if opts.include_jited_prog_insns {
347 jited_prog_insns.resize(item.jited_prog_len as usize, 0u8);
348 item.jited_prog_insns = jited_prog_insns.as_mut_ptr().cast::<c_void>() as u64;
349 } else {
350 item.jited_prog_len = 0;
351 }
352
353 if opts.include_map_ids {
354 map_ids.resize(item.nr_map_ids as usize, 0u32);
355 item.map_ids = map_ids.as_mut_ptr().cast::<c_void>() as u64;
356 } else {
357 item.nr_map_ids = 0;
358 }
359
360 if opts.include_line_info {
361 line_info.resize(
362 item.nr_line_info as usize,
363 libbpf_sys::bpf_line_info::default(),
364 );
365 item.line_info = line_info.as_mut_ptr().cast::<c_void>() as u64;
366 } else {
367 item.nr_line_info = 0;
368 }
369
370 if opts.include_func_info {
371 func_info.resize(
372 item.nr_func_info as usize,
373 libbpf_sys::bpf_func_info::default(),
374 );
375 item.func_info = func_info.as_mut_ptr().cast::<c_void>() as u64;
376 } else {
377 item.nr_func_info = 0;
378 }
379
380 if opts.include_jited_line_info {
381 jited_line_info.resize(item.nr_jited_line_info as usize, ptr::null());
382 item.jited_line_info = jited_line_info.as_mut_ptr().cast::<c_void>() as u64;
383 } else {
384 item.nr_jited_line_info = 0;
385 }
386
387 if opts.include_jited_func_lens {
388 jited_func_lens.resize(item.nr_jited_func_lens as usize, 0);
389 item.jited_func_lens = jited_func_lens.as_mut_ptr().cast::<c_void>() as u64;
390 } else {
391 item.nr_jited_func_lens = 0;
392 }
393
394 if opts.include_prog_tags {
395 prog_tags.resize(item.nr_prog_tags as usize, Tag::default());
396 item.prog_tags = prog_tags.as_mut_ptr().cast::<c_void>() as u64;
397 } else {
398 item.nr_prog_tags = 0;
399 }
400
401 if opts.include_jited_ksyms {
402 jited_ksyms.resize(item.nr_jited_ksyms as usize, ptr::null());
403 item.jited_ksyms = jited_ksyms.as_mut_ptr().cast::<c_void>() as u64;
404 } else {
405 item.nr_jited_ksyms = 0;
406 }
407
408 let ret = unsafe {
409 libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr.cast::<c_void>(), &mut len)
410 };
411 util::parse_ret(ret)?;
412
413 Ok(Self {
414 name: cstr_to_os_string(name),
415 ty,
416 tag: Tag(item.tag),
417 id: item.id,
418 jited_prog_insns,
419 xlated_prog_insns,
420 load_time: Duration::from_nanos(item.load_time),
421 created_by_uid: item.created_by_uid,
422 map_ids,
423 ifindex: item.ifindex,
424 gpl_compatible: item._bitfield_1.get_bit(0),
425 netns_dev: item.netns_dev,
426 netns_ino: item.netns_ino,
427 jited_ksyms,
428 jited_func_lens,
429 btf_id: item.btf_id,
430 func_info_rec_size: item.func_info_rec_size,
431 func_info,
432 line_info: line_info.iter().map(Into::into).collect(),
433 jited_line_info,
434 line_info_rec_size: item.line_info_rec_size,
435 jited_line_info_rec_size: item.jited_line_info_rec_size,
436 prog_tags,
437 run_time_ns: item.run_time_ns,
438 run_cnt: item.run_cnt,
439 recursion_misses: item.recursion_misses,
440 verified_insns: item.verified_insns,
441 _non_exhaustive: (),
442 })
443 }
444}
445
446impl ProgInfoIter {
447 fn next_valid_fd(&mut self) -> Option<OwnedFd> {
448 loop {
449 if unsafe { libbpf_sys::bpf_prog_get_next_id(self.cur_id, &mut self.cur_id) } != 0 {
450 return None;
451 }
452
453 let fd = unsafe { libbpf_sys::bpf_prog_get_fd_by_id(self.cur_id) };
454 if fd < 0 {
455 let err = io::Error::last_os_error();
456 if err.kind() == io::ErrorKind::NotFound {
457 continue;
458 }
459 return None;
460 }
461
462 return Some(unsafe { OwnedFd::from_raw_fd(fd) });
463 }
464 }
465}
466
467impl Iterator for ProgInfoIter {
468 type Item = ProgramInfo;
469
470 fn next(&mut self) -> Option<Self::Item> {
471 let fd = self.next_valid_fd()?;
472 let prog = ProgramInfo::load_from_fd(fd.as_fd(), &self.opts);
473 prog.ok()
474 }
475}
476
477#[derive(Debug, Clone)]
479#[doc(alias = "bpf_map_info")]
480pub struct MapInfo {
481 pub name: OsString,
483 pub ty: MapType,
485 pub id: u32,
487 pub key_size: u32,
489 pub value_size: u32,
491 pub max_entries: u32,
493 pub map_flags: u32,
495 pub ifindex: u32,
498 pub btf_vmlinux_value_type_id: u32,
500 pub netns_dev: u64,
502 pub netns_ino: u64,
504 pub btf_id: u32,
507 pub btf_key_type_id: u32,
509 pub btf_value_type_id: u32,
511}
512
513impl MapInfo {
514 fn from_uapi(_fd: BorrowedFd<'_>, s: libbpf_sys::bpf_map_info) -> Option<Self> {
515 let name = util::c_char_slice_to_cstr(&s.name).unwrap();
517 let ty = MapType::from(s.type_);
518
519 Some(Self {
520 name: cstr_to_os_string(name),
521 ty,
522 id: s.id,
523 key_size: s.key_size,
524 value_size: s.value_size,
525 max_entries: s.max_entries,
526 map_flags: s.map_flags,
527 ifindex: s.ifindex,
528 btf_vmlinux_value_type_id: s.btf_vmlinux_value_type_id,
529 netns_dev: s.netns_dev,
530 netns_ino: s.netns_ino,
531 btf_id: s.btf_id,
532 btf_key_type_id: s.btf_key_type_id,
533 btf_value_type_id: s.btf_value_type_id,
534 })
535 }
536}
537
538gen_info_impl!(
539 #[doc(alias = "bpf_map_get_next_id")]
541 MapInfoIter,
542 MapInfo,
543 libbpf_sys::bpf_map_info,
544 libbpf_sys::bpf_map_get_next_id,
545 libbpf_sys::bpf_map_get_fd_by_id
546);
547
548#[derive(Debug, Clone)]
550#[doc(alias = "bpf_btf_info")]
551pub struct BtfInfo {
552 pub name: OsString,
554 pub btf: Vec<u8>,
556 pub id: u32,
558}
559
560impl BtfInfo {
561 fn load_from_fd(fd: BorrowedFd<'_>) -> Result<Self> {
562 let mut item = libbpf_sys::bpf_btf_info::default();
563 let mut btf: Vec<u8> = Vec::new();
564 let mut name: Vec<u8> = Vec::new();
565
566 let item_ptr: *mut libbpf_sys::bpf_btf_info = &mut item;
567 let mut len = size_of_val(&item) as u32;
568
569 let ret = unsafe {
570 libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr.cast::<c_void>(), &mut len)
571 };
572 util::parse_ret(ret)?;
573
574 item.name_len += 1;
577 name.resize(item.name_len as usize, 0u8);
578 item.name = name.as_mut_ptr().cast::<c_void>() as u64;
579
580 btf.resize(item.btf_size as usize, 0u8);
581 item.btf = btf.as_mut_ptr().cast::<c_void>() as u64;
582
583 let ret = unsafe {
584 libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr.cast::<c_void>(), &mut len)
585 };
586 util::parse_ret(ret)?;
587
588 Ok(Self {
589 name: cstr_to_os_string(CStr::from_bytes_with_nul(&name).unwrap()),
593 btf,
594 id: item.id,
595 })
596 }
597}
598
599#[derive(Debug, Default)]
600#[doc(alias = "bpf_btf_get_next_id")]
603#[doc(alias = "bpf_btf_get_fd_by_id")]
604pub struct BtfInfoIter {
605 cur_id: u32,
606}
607
608impl BtfInfoIter {
609 fn next_valid_fd(&mut self) -> Option<OwnedFd> {
611 loop {
612 if unsafe { libbpf_sys::bpf_btf_get_next_id(self.cur_id, &mut self.cur_id) } != 0 {
613 return None;
614 }
615
616 let fd = unsafe { libbpf_sys::bpf_btf_get_fd_by_id(self.cur_id) };
617 if fd < 0 {
618 let err = io::Error::last_os_error();
619 if err.kind() == io::ErrorKind::NotFound {
620 continue;
621 }
622 return None;
623 }
624
625 return Some(unsafe { OwnedFd::from_raw_fd(fd) });
626 }
627 }
628}
629
630impl Iterator for BtfInfoIter {
631 type Item = BtfInfo;
632
633 fn next(&mut self) -> Option<Self::Item> {
634 let fd = self.next_valid_fd()?;
635 let info = BtfInfo::load_from_fd(fd.as_fd());
636 info.ok()
637 }
638}
639
640#[derive(Debug, Clone)]
642pub struct RawTracepointLinkInfo {
643 pub name: String,
645 #[doc(hidden)]
647 pub _non_exhaustive: (),
648}
649
650#[derive(Debug, Clone)]
652pub struct TracingLinkInfo {
653 pub attach_type: ProgramAttachType,
655 pub target_obj_id: u32,
658 pub target_btf_id: u32,
660 #[doc(hidden)]
662 pub _non_exhaustive: (),
663}
664
665#[derive(Debug, Clone)]
667pub struct CgroupLinkInfo {
668 pub cgroup_id: u64,
670 pub attach_type: ProgramAttachType,
672 #[doc(hidden)]
674 pub _non_exhaustive: (),
675}
676
677#[derive(Debug, Clone)]
679pub struct IterLinkInfo {
680 pub target_name: OsString,
682 pub iter_type: IterType,
684 #[doc(hidden)]
686 pub _non_exhaustive: (),
687}
688
689#[derive(Debug, Clone)]
691pub enum IterType {
692 Map {
694 map_id: u32,
696 },
697 Cgroup {
699 cgroup_id: u64,
701 order: CgroupIterOrder,
703 },
704 Task {
706 tid: u32,
708 pid: u32,
710 },
711 Unknown,
716}
717
718#[derive(Debug, Clone)]
720pub struct NetNsLinkInfo {
721 pub ino: u32,
723 pub attach_type: ProgramAttachType,
725 #[doc(hidden)]
727 pub _non_exhaustive: (),
728}
729
730#[derive(Debug, Clone)]
732pub struct NetfilterLinkInfo {
733 pub protocol_family: u32,
735 pub hooknum: u32,
737 pub priority: i32,
739 pub flags: u32,
741 #[doc(hidden)]
743 pub _non_exhaustive: (),
744}
745
746#[derive(Debug, Clone)]
748pub struct XdpLinkInfo {
749 pub ifindex: u32,
751 #[doc(hidden)]
753 pub _non_exhaustive: (),
754}
755
756#[derive(Debug, Clone)]
758pub struct SockMapLinkInfo {
759 pub map_id: u32,
761 pub attach_type: ProgramAttachType,
763 #[doc(hidden)]
765 pub _non_exhaustive: (),
766}
767
768#[derive(Debug, Clone)]
770pub struct NetkitLinkInfo {
771 pub ifindex: u32,
773 pub attach_type: ProgramAttachType,
775 #[doc(hidden)]
777 pub _non_exhaustive: (),
778}
779
780#[derive(Debug, Clone)]
782pub struct TcxLinkInfo {
783 pub ifindex: u32,
785 pub attach_type: ProgramAttachType,
787 #[doc(hidden)]
789 pub _non_exhaustive: (),
790}
791
792#[derive(Debug, Clone)]
794pub struct StructOpsLinkInfo {
795 pub map_id: u32,
797 #[doc(hidden)]
799 pub _non_exhaustive: (),
800}
801
802#[derive(Debug, Clone)]
804pub struct KprobeMultiLinkInfo {
805 pub count: u32,
807 pub flags: u32,
809 pub missed: u64,
811 pub addrs: Vec<u64>,
813 pub cookies: Vec<u64>,
815 #[doc(hidden)]
817 pub _non_exhaustive: (),
818}
819
820#[derive(Debug, Clone)]
822pub struct UprobeMultiLinkInfo {
823 pub path_size: u32,
825 pub path: Option<PathBuf>,
827 pub count: u32,
829 pub flags: u32,
831 pub pid: u32,
833 pub offsets: Vec<u64>,
835 pub ref_ctr_offsets: Vec<u64>,
837 pub cookies: Vec<u64>,
839 #[doc(hidden)]
841 pub _non_exhaustive: (),
842}
843
844#[derive(Debug, Clone)]
846pub struct PerfEventLinkInfo {
847 pub event_type: PerfEventType,
849 #[doc(hidden)]
851 pub _non_exhaustive: (),
852}
853
854#[derive(Debug, Clone)]
856pub enum PerfEventType {
857 Tracepoint {
859 name: Option<OsString>,
861 cookie: u64,
863 },
864 Kprobe {
866 func_name: Option<OsString>,
868 is_retprobe: bool,
870 addr: u64,
872 offset: u32,
874 missed: u64,
876 cookie: u64,
878 },
879 Uprobe {
881 file_name: Option<OsString>,
883 is_retprobe: bool,
885 offset: u32,
887 cookie: u64,
889 ref_ctr_offset: u64,
891 },
892 Event {
894 config: u64,
896 event_type: u32,
898 cookie: u64,
900 },
901 Unknown(u32),
903}
904
905#[derive(Debug, Clone)]
908pub enum LinkTypeInfo {
909 RawTracepoint(RawTracepointLinkInfo),
913 Tracing(TracingLinkInfo),
915 Cgroup(CgroupLinkInfo),
919 Iter(IterLinkInfo),
921 NetNs(NetNsLinkInfo),
923 Xdp(XdpLinkInfo),
928 StructOps(StructOpsLinkInfo),
933 Netfilter(NetfilterLinkInfo),
935 KprobeMulti(KprobeMultiLinkInfo),
937 UprobeMulti(UprobeMultiLinkInfo),
939 Tcx(TcxLinkInfo),
941 Netkit(NetkitLinkInfo),
943 SockMap(SockMapLinkInfo),
945 PerfEvent(PerfEventLinkInfo),
950 Unknown,
952}
953
954#[derive(Debug, Clone)]
956#[doc(alias = "bpf_link_info")]
957pub struct LinkInfo {
958 pub info: LinkTypeInfo,
960 pub id: u32,
962 pub prog_id: u32,
964}
965
966impl LinkInfo {
967 #[doc(alias = "bpf_obj_get_info_by_fd")]
969 pub fn from_fd(fd: BorrowedFd<'_>) -> Result<Self> {
970 let mut link_info: libbpf_sys::bpf_link_info = unsafe { zeroed() };
972 let item_ptr: *mut libbpf_sys::bpf_link_info = &mut link_info;
973 let mut len = size_of_val(&link_info) as u32;
974
975 let ret = unsafe {
976 libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr.cast::<c_void>(), &mut len)
977 };
978 util::parse_ret(ret)?;
979
980 Self::from_uapi(fd, link_info)
981 .ok_or_else(|| crate::Error::with_invalid_data("failed to parse link info"))
982 }
983
984 fn from_uapi(fd: BorrowedFd<'_>, mut s: libbpf_sys::bpf_link_info) -> Option<Self> {
985 let type_info = match s.type_ {
986 libbpf_sys::BPF_LINK_TYPE_RAW_TRACEPOINT => {
987 let mut buf = [0u8; 256];
988 s.__bindgen_anon_1.raw_tracepoint.tp_name = buf.as_mut_ptr() as u64;
989 s.__bindgen_anon_1.raw_tracepoint.tp_name_len = buf.len() as u32;
990 let item_ptr: *mut libbpf_sys::bpf_link_info = &mut s;
991 let mut len = size_of_val(&s) as u32;
992
993 let ret = unsafe {
994 libbpf_sys::bpf_obj_get_info_by_fd(
995 fd.as_raw_fd(),
996 item_ptr.cast::<c_void>(),
997 &mut len,
998 )
999 };
1000 if ret != 0 {
1001 return None;
1002 }
1003
1004 LinkTypeInfo::RawTracepoint(RawTracepointLinkInfo {
1005 name: util::c_ptr_to_string(
1006 unsafe { s.__bindgen_anon_1.raw_tracepoint.tp_name } as *const c_char,
1007 )
1008 .unwrap_or_else(|_| "?".to_string()),
1009 _non_exhaustive: (),
1010 })
1011 }
1012 libbpf_sys::BPF_LINK_TYPE_TRACING => LinkTypeInfo::Tracing(TracingLinkInfo {
1013 attach_type: ProgramAttachType::from(unsafe {
1014 s.__bindgen_anon_1.tracing.attach_type
1015 }),
1016 target_obj_id: unsafe { s.__bindgen_anon_1.tracing.target_obj_id },
1017 target_btf_id: unsafe { s.__bindgen_anon_1.tracing.target_btf_id },
1018 _non_exhaustive: (),
1019 }),
1020 libbpf_sys::BPF_LINK_TYPE_CGROUP => LinkTypeInfo::Cgroup(CgroupLinkInfo {
1021 cgroup_id: unsafe { s.__bindgen_anon_1.cgroup.cgroup_id },
1022 attach_type: ProgramAttachType::from(unsafe {
1023 s.__bindgen_anon_1.cgroup.attach_type
1024 }),
1025 _non_exhaustive: (),
1026 }),
1027 libbpf_sys::BPF_LINK_TYPE_ITER => {
1028 let mut buf = [0u8; 256];
1029 s.__bindgen_anon_1.iter.target_name = buf.as_mut_ptr() as u64;
1030 s.__bindgen_anon_1.iter.target_name_len = buf.len() as u32;
1031 let item_ptr: *mut libbpf_sys::bpf_link_info = &mut s;
1032 let mut len = size_of_val(&s) as u32;
1033
1034 let ret = unsafe {
1035 libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr.cast(), &mut len)
1036 };
1037 if ret != 0 {
1038 return None;
1039 }
1040
1041 let iter_info = unsafe { s.__bindgen_anon_1.iter };
1042 let target_name = unsafe {
1046 cstr_to_os_string(CStr::from_ptr(iter_info.target_name as *const c_char))
1047 };
1048
1049 let iter_type = match target_name.as_bytes() {
1050 b"bpf_map_elem" | b"bpf_sk_storage_map" => IterType::Map {
1051 map_id: unsafe { iter_info.__bindgen_anon_1.map.map_id },
1052 },
1053 b"cgroup" => {
1054 let order = match unsafe { iter_info.__bindgen_anon_2.cgroup.order } {
1055 libbpf_sys::BPF_CGROUP_ITER_SELF_ONLY => CgroupIterOrder::SelfOnly,
1056 libbpf_sys::BPF_CGROUP_ITER_DESCENDANTS_PRE => {
1057 CgroupIterOrder::DescendantsPre
1058 }
1059 libbpf_sys::BPF_CGROUP_ITER_DESCENDANTS_POST => {
1060 CgroupIterOrder::DescendantsPost
1061 }
1062 libbpf_sys::BPF_CGROUP_ITER_ANCESTORS_UP => {
1063 CgroupIterOrder::AncestorsUp
1064 }
1065 _ => CgroupIterOrder::Default,
1066 };
1067 IterType::Cgroup {
1068 cgroup_id: unsafe { iter_info.__bindgen_anon_2.cgroup.cgroup_id },
1069 order,
1070 }
1071 }
1072 b"task" | b"task_file" | b"task_vma" => IterType::Task {
1073 tid: unsafe { iter_info.__bindgen_anon_2.task.tid },
1074 pid: unsafe { iter_info.__bindgen_anon_2.task.pid },
1075 },
1076 _ => IterType::Unknown,
1077 };
1078
1079 LinkTypeInfo::Iter(IterLinkInfo {
1080 target_name,
1081 iter_type,
1082 _non_exhaustive: (),
1083 })
1084 }
1085 libbpf_sys::BPF_LINK_TYPE_NETNS => LinkTypeInfo::NetNs(NetNsLinkInfo {
1086 ino: unsafe { s.__bindgen_anon_1.netns.netns_ino },
1087 attach_type: ProgramAttachType::from(unsafe {
1088 s.__bindgen_anon_1.netns.attach_type
1089 }),
1090 _non_exhaustive: (),
1091 }),
1092 libbpf_sys::BPF_LINK_TYPE_NETFILTER => LinkTypeInfo::Netfilter(NetfilterLinkInfo {
1093 protocol_family: unsafe { s.__bindgen_anon_1.netfilter.pf },
1094 hooknum: unsafe { s.__bindgen_anon_1.netfilter.hooknum },
1095 priority: unsafe { s.__bindgen_anon_1.netfilter.priority },
1096 flags: unsafe { s.__bindgen_anon_1.netfilter.flags },
1097 _non_exhaustive: (),
1098 }),
1099 libbpf_sys::BPF_LINK_TYPE_XDP => LinkTypeInfo::Xdp(XdpLinkInfo {
1100 ifindex: unsafe { s.__bindgen_anon_1.xdp.ifindex },
1101 _non_exhaustive: (),
1102 }),
1103 libbpf_sys::BPF_LINK_TYPE_NETKIT => LinkTypeInfo::Netkit(NetkitLinkInfo {
1104 ifindex: unsafe { s.__bindgen_anon_1.netkit.ifindex },
1105 attach_type: ProgramAttachType::from(unsafe {
1106 s.__bindgen_anon_1.netkit.attach_type
1107 }),
1108 _non_exhaustive: (),
1109 }),
1110 libbpf_sys::BPF_LINK_TYPE_TCX => LinkTypeInfo::Tcx(TcxLinkInfo {
1111 ifindex: unsafe { s.__bindgen_anon_1.tcx.ifindex },
1112 attach_type: ProgramAttachType::from(unsafe { s.__bindgen_anon_1.tcx.attach_type }),
1113 _non_exhaustive: (),
1114 }),
1115 libbpf_sys::BPF_LINK_TYPE_STRUCT_OPS => LinkTypeInfo::StructOps(StructOpsLinkInfo {
1116 map_id: unsafe { s.__bindgen_anon_1.struct_ops.map_id },
1117 _non_exhaustive: (),
1118 }),
1119 libbpf_sys::BPF_LINK_TYPE_KPROBE_MULTI => {
1120 let count = unsafe { s.__bindgen_anon_1.kprobe_multi.count } as usize;
1121 let mut addrs = vec![0; count];
1122 let mut cookies = vec![0; count];
1123
1124 s.__bindgen_anon_1.kprobe_multi.addrs = addrs.as_mut_ptr() as u64;
1125 s.__bindgen_anon_1.kprobe_multi.cookies = cookies.as_mut_ptr() as u64;
1126 let item_ptr: *mut libbpf_sys::bpf_link_info = &mut s;
1127 let mut len = size_of_val(&s) as u32;
1128 let ret = unsafe {
1129 libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr.cast(), &mut len)
1130 };
1131 if ret != 0 {
1132 return None;
1133 }
1134
1135 LinkTypeInfo::KprobeMulti(KprobeMultiLinkInfo {
1136 count: unsafe { s.__bindgen_anon_1.kprobe_multi.count },
1137 flags: unsafe { s.__bindgen_anon_1.kprobe_multi.flags },
1138 missed: unsafe { s.__bindgen_anon_1.kprobe_multi.missed },
1139 addrs,
1140 cookies,
1141 _non_exhaustive: (),
1142 })
1143 }
1144 libbpf_sys::BPF_LINK_TYPE_UPROBE_MULTI => {
1145 let mut buf = [0u8; libc::PATH_MAX as usize];
1146 let count = unsafe { s.__bindgen_anon_1.uprobe_multi.count } as usize;
1147 let mut offsets = vec![0; count];
1148 let mut ref_ctr_offsets = vec![0; count];
1149 let mut cookies = vec![0; count];
1150
1151 s.__bindgen_anon_1.uprobe_multi.path = buf.as_mut_ptr() as u64;
1152 s.__bindgen_anon_1.uprobe_multi.path_size = buf.len() as u32;
1153 s.__bindgen_anon_1.uprobe_multi.offsets = offsets.as_mut_ptr() as u64;
1154 s.__bindgen_anon_1.uprobe_multi.ref_ctr_offsets =
1155 ref_ctr_offsets.as_mut_ptr() as u64;
1156 s.__bindgen_anon_1.uprobe_multi.cookies = cookies.as_mut_ptr() as u64;
1157 let item_ptr: *mut libbpf_sys::bpf_link_info = &mut s;
1158 let mut len = size_of_val(&s) as u32;
1159 let ret = unsafe {
1160 libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr.cast(), &mut len)
1161 };
1162 if ret != 0 {
1163 return None;
1164 }
1165
1166 let path_size = unsafe { s.__bindgen_anon_1.uprobe_multi.path_size };
1167 let path = if path_size != 0 {
1168 let path_ptr = unsafe { s.__bindgen_anon_1.uprobe_multi.path } as *const c_char;
1169 let c_str = unsafe { CStr::from_ptr(path_ptr) };
1170 Some(PathBuf::from(OsStr::from_bytes(c_str.to_bytes())))
1171 } else {
1172 None
1173 };
1174
1175 LinkTypeInfo::UprobeMulti(UprobeMultiLinkInfo {
1176 path_size,
1177 path,
1178 count: unsafe { s.__bindgen_anon_1.uprobe_multi.count },
1179 flags: unsafe { s.__bindgen_anon_1.uprobe_multi.flags },
1180 pid: unsafe { s.__bindgen_anon_1.uprobe_multi.pid },
1181 offsets,
1182 ref_ctr_offsets,
1183 cookies,
1184 _non_exhaustive: (),
1185 })
1186 }
1187 libbpf_sys::BPF_LINK_TYPE_SOCKMAP => LinkTypeInfo::SockMap(SockMapLinkInfo {
1188 map_id: unsafe { s.__bindgen_anon_1.sockmap.map_id },
1189 attach_type: ProgramAttachType::from(unsafe {
1190 s.__bindgen_anon_1.sockmap.attach_type
1191 }),
1192 _non_exhaustive: (),
1193 }),
1194 libbpf_sys::BPF_LINK_TYPE_PERF_EVENT => {
1195 let bpf_perf_event_type = unsafe { s.__bindgen_anon_1.perf_event.type_ };
1197
1198 let mut buf = [0u8; libc::PATH_MAX as usize];
1204 let call_get_info_again = match bpf_perf_event_type {
1205 libbpf_sys::BPF_PERF_EVENT_TRACEPOINT => {
1206 s.__bindgen_anon_1
1207 .perf_event
1208 .__bindgen_anon_1
1209 .tracepoint
1210 .tp_name = buf.as_mut_ptr() as u64;
1211 s.__bindgen_anon_1
1212 .perf_event
1213 .__bindgen_anon_1
1214 .tracepoint
1215 .name_len = buf.len() as u32;
1216 true
1217 }
1218 libbpf_sys::BPF_PERF_EVENT_KPROBE | libbpf_sys::BPF_PERF_EVENT_KRETPROBE => {
1219 s.__bindgen_anon_1
1220 .perf_event
1221 .__bindgen_anon_1
1222 .kprobe
1223 .func_name = buf.as_mut_ptr() as u64;
1224 s.__bindgen_anon_1
1225 .perf_event
1226 .__bindgen_anon_1
1227 .kprobe
1228 .name_len = buf.len() as u32;
1229 true
1230 }
1231 libbpf_sys::BPF_PERF_EVENT_UPROBE | libbpf_sys::BPF_PERF_EVENT_URETPROBE => {
1232 let uprobe =
1234 unsafe { &mut s.__bindgen_anon_1.perf_event.__bindgen_anon_1.uprobe };
1235 uprobe.file_name = buf.as_mut_ptr() as u64;
1236 uprobe.name_len = buf.len() as u32;
1237 true
1238 }
1239 _ => false,
1240 };
1241
1242 if call_get_info_again {
1243 let item_ptr: *mut libbpf_sys::bpf_link_info = &mut s;
1244 let mut len = size_of_val(&s) as u32;
1245 let ret = unsafe {
1246 libbpf_sys::bpf_obj_get_info_by_fd(
1247 fd.as_raw_fd(),
1248 item_ptr.cast::<c_void>(),
1249 &mut len,
1250 )
1251 };
1252 if ret != 0 {
1253 return None;
1254 }
1255 }
1256
1257 let event_type = match bpf_perf_event_type {
1258 libbpf_sys::BPF_PERF_EVENT_TRACEPOINT => {
1259 let tp_name = unsafe {
1260 s.__bindgen_anon_1
1261 .perf_event
1262 .__bindgen_anon_1
1263 .tracepoint
1264 .tp_name
1265 };
1266 let cookie = unsafe {
1267 s.__bindgen_anon_1
1268 .perf_event
1269 .__bindgen_anon_1
1270 .tracepoint
1271 .cookie
1272 };
1273 let name = (tp_name != 0).then(|| unsafe {
1274 cstr_to_os_string(CStr::from_ptr(tp_name as *const c_char))
1275 });
1276
1277 PerfEventType::Tracepoint { name, cookie }
1278 }
1279 libbpf_sys::BPF_PERF_EVENT_KPROBE | libbpf_sys::BPF_PERF_EVENT_KRETPROBE => {
1280 let func_name = unsafe {
1281 s.__bindgen_anon_1
1282 .perf_event
1283 .__bindgen_anon_1
1284 .kprobe
1285 .func_name
1286 };
1287 let addr =
1288 unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.kprobe.addr };
1289 let offset =
1290 unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.kprobe.offset };
1291 let missed =
1292 unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.kprobe.missed };
1293 let cookie =
1294 unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.kprobe.cookie };
1295 let func_name = (func_name != 0).then(|| unsafe {
1296 cstr_to_os_string(CStr::from_ptr(func_name as *const c_char))
1297 });
1298
1299 let is_retprobe =
1300 bpf_perf_event_type == libbpf_sys::BPF_PERF_EVENT_KRETPROBE;
1301 PerfEventType::Kprobe {
1302 func_name,
1303 is_retprobe,
1304 addr,
1305 offset,
1306 missed,
1307 cookie,
1308 }
1309 }
1310 libbpf_sys::BPF_PERF_EVENT_UPROBE | libbpf_sys::BPF_PERF_EVENT_URETPROBE => {
1311 let uprobe =
1313 unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.uprobe };
1314 let file_name = (uprobe.file_name != 0).then(|| unsafe {
1316 cstr_to_os_string(CStr::from_ptr(uprobe.file_name as *const c_char))
1317 });
1318
1319 PerfEventType::Uprobe {
1320 file_name,
1321 is_retprobe: bpf_perf_event_type
1322 == libbpf_sys::BPF_PERF_EVENT_URETPROBE,
1323 offset: uprobe.offset,
1324 cookie: uprobe.cookie,
1325 ref_ctr_offset: uprobe.ref_ctr_offset,
1326 }
1327 }
1328 libbpf_sys::BPF_PERF_EVENT_EVENT => {
1329 let event = unsafe { s.__bindgen_anon_1.perf_event.__bindgen_anon_1.event };
1331
1332 PerfEventType::Event {
1333 config: event.config,
1334 event_type: event.type_,
1335 cookie: event.cookie,
1336 }
1337 }
1338 ty => PerfEventType::Unknown(ty),
1339 };
1340
1341 LinkTypeInfo::PerfEvent(PerfEventLinkInfo {
1342 event_type,
1343 _non_exhaustive: (),
1344 })
1345 }
1346 _ => LinkTypeInfo::Unknown,
1347 };
1348
1349 Some(Self {
1350 info: type_info,
1351 id: s.id,
1352 prog_id: s.prog_id,
1353 })
1354 }
1355}
1356
1357gen_info_impl!(
1358 #[doc(alias = "bpf_link_get_next_id")]
1360 #[doc(alias = "bpf_link_get_fd_by_id")]
1361 LinkInfoIter,
1362 LinkInfo,
1363 libbpf_sys::bpf_link_info,
1364 libbpf_sys::bpf_link_get_next_id,
1365 libbpf_sys::bpf_link_get_fd_by_id
1366);