1use crate::error::Error;
2use crate::platform::linux::bpf::{AttachType, CallBpf, Command};
3use crate::platform::linux::syscalls::close;
4
5use std::io::Write;
6
7#[derive(Default)]
8#[repr(C, align(8))]
9#[derive(Copy, Clone)]
10struct BpfProgramAttr {
11 pub prog_type: u32,
12 pub insn_cnt: u32,
13 pub insns: u64,
14 pub license: u64,
15 pub log_level: u32,
16 pub log_size: u32,
17 pub log_buf: u64,
18 pub kern_version: u32,
19 pub prog_flags: u32,
20 pub prog_name: [u8; 16],
21 pub prog_ifindex: u32,
22 pub expected_attach_type: u32,
23 pub prog_btf_fd: u32,
24 pub func_info_rec_size: u32,
25 pub func_info: u64,
26 pub func_info_count: u32,
27 pub line_info_rec_size: u32,
28 pub line_info: u64,
29 pub line_info_count: u32,
30 pub attach_btf_id: u32,
31}
32
33impl CallBpf for BpfProgramAttr {}
34
35#[derive(Copy, Clone)]
36pub enum ProgramType {
37 Unspec = 0,
38 SocketFilter,
39 KProbe,
40 SchedCls,
41 SchedAct,
42 Tracepoint,
43 Xdp,
44 PerfEvent,
45 CgroupSkb,
46 CgroupSock,
47 LwtIn,
48 LwtOut,
49 LwtXmit,
50 SockOps,
51 SkSkb,
52 CgroupDevice,
53 SkMsg,
54 RawTracepoint,
55 CgroupSockAddr,
56 LwtSeg6local,
57 LircMode2,
58 SkReuseport,
59 FlowDissector,
60 CgroupSysctl,
61 RawTracepointWritable,
62 CgroupSockopt,
63 Tracing,
64 StructOps,
65 Ext,
66 Lsm,
67 SkLookup,
68 Syscall,
69}
70
71#[derive(Clone)]
72pub struct ProgramAttr {
73 pub prog_name: Option<String>,
75
76 pub prog_type: ProgramType,
79
80 pub expected_attach_type: Option<AttachType>,
82
83 pub attach_btf_id: Option<u32>,
85}
86
87pub struct Program {
88 attr: ProgramAttr,
89 fd: u32,
90}
91
92impl Program {
93 const LICENSE: &'static str = "GPL\0";
94
95 pub fn create(
105 attr: &ProgramAttr,
106 instructions: &[u64],
107 log_out: Option<&mut dyn Write>,
108 ) -> Result<Self, Error> {
109 let mut buf = vec![0; 1 << 20];
110
111 let expected_attach_type = if let Some(t) = attr.expected_attach_type {
112 t as u32
113 } else {
114 0
115 };
116
117 let attach_btf_id = if let Some(id) = attr.attach_btf_id {
118 id
119 } else {
120 0
121 };
122
123 let mut prog_name: [u8; 16] = [0; 16];
124 if let Some(name) = &attr.prog_name {
125 for (i, c) in name.chars().enumerate() {
126 if i == 16 {
127 break;
128 }
129 prog_name[i] = c as u8;
130 }
131 }
132
133 let bpf_attr = BpfProgramAttr {
134 prog_type: attr.prog_type as u32,
135 insns: instructions.as_ptr() as u64,
136 insn_cnt: instructions.len() as u32,
137 license: Self::LICENSE.as_ptr() as u64,
138 log_level: 1,
139 log_size: 1 << 20,
140 log_buf: buf.as_mut_ptr() as u64,
141 kern_version: 0,
142 prog_flags: 0,
143 prog_name,
144 prog_ifindex: 0,
145 expected_attach_type,
146 prog_btf_fd: 0,
147 func_info_rec_size: 0,
148 func_info: 0,
149 func_info_count: 0,
150 line_info_rec_size: 0,
151 line_info: 0,
152 line_info_count: 0,
153 attach_btf_id,
154 };
155
156 let r = bpf_attr.call_bpf(Command::ProgLoad);
157
158 if let (Ok(s), Some(log_out)) = (std::str::from_utf8(&buf), log_out) {
159 let _ = write!(log_out, "{}", s);
160 }
161
162 match r {
163 Err(e) => Err(e),
164 Ok(r) => Ok(Self {
165 fd: r,
166 attr: attr.clone(),
167 }),
168 }
169 }
170
171 pub fn get_attr(&self) -> &ProgramAttr {
173 &self.attr
174 }
175
176 pub fn get_fd(&self) -> u32 {
178 self.fd
179 }
180}
181
182impl Drop for Program {
183 fn drop(&mut self) {
184 close(self.fd);
185 }
186}