1pub mod config;
5pub mod util;
6#[path = "bpfd.v1.rs"]
7#[rustfmt::skip]
8#[allow(clippy::all)]
9pub mod v1;
10use clap::ValueEnum;
11use serde::{Deserialize, Serialize};
12use thiserror::Error;
13use url::ParseError as urlParseError;
14use v1::bytecode_location::Location;
15
16#[derive(Error, Debug)]
17pub enum ParseError {
18 #[error("{program} is not a valid program type")]
19 InvalidProgramType { program: String },
20 #[error("{proceedon} is not a valid proceed-on value")]
21 InvalidProceedOn { proceedon: String },
22 #[error("not a valid direction: {direction}")]
23 InvalidDirection { direction: String },
24 #[error("Failed to Parse bytecode location: {0}")]
25 BytecodeLocationParseFailure(#[source] urlParseError),
26 #[error("Invalid bytecode location: {location}")]
27 InvalidBytecodeLocation { location: String },
28 #[error("Invalid bytecode image pull policy: {pull_policy}")]
29 InvalidBytecodeImagePullPolicy { pull_policy: String },
30 #[error("{probe} is not a valid probe type")]
31 InvalidProbeType { probe: String },
32}
33
34#[derive(ValueEnum, Copy, Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
35pub enum ProgramType {
36 Unspec,
37 SocketFilter,
38 Probe, Tc,
40 SchedAct,
41 Tracepoint,
42 Xdp,
43 PerfEvent,
44 CgroupSkb,
45 CgroupSock,
46 LwtIn,
47 LwtOut,
48 LwtXmit,
49 SockOps,
50 SkSkb,
51 CgroupDevice,
52 SkMsg,
53 RawTracepoint,
54 CgroupSockAddr,
55 LwtSeg6Local,
56 LircMode2,
57 SkReuseport,
58 FlowDissector,
59 CgroupSysctl,
60 RawTracepointWritable,
61 CgroupSockopt,
62 Tracing,
63 StructOps,
64 Ext,
65 Lsm,
66 SkLookup,
67 Syscall,
68}
69
70impl TryFrom<String> for ProgramType {
71 type Error = ParseError;
72
73 fn try_from(value: String) -> Result<Self, Self::Error> {
74 Ok(match value.as_str() {
75 "unspec" => ProgramType::Unspec,
76 "socket_filter" => ProgramType::SocketFilter,
77 "probe" => ProgramType::Probe,
78 "tc" => ProgramType::Tc,
79 "sched_act" => ProgramType::SchedAct,
80 "tracepoint" => ProgramType::Tracepoint,
81 "xdp" => ProgramType::Xdp,
82 "perf_event" => ProgramType::PerfEvent,
83 "cgroup_skb" => ProgramType::CgroupSkb,
84 "cgroup_sock" => ProgramType::CgroupSock,
85 "lwt_in" => ProgramType::LwtIn,
86 "lwt_out" => ProgramType::LwtOut,
87 "lwt_xmit" => ProgramType::LwtXmit,
88 "sock_ops" => ProgramType::SockOps,
89 "sk_skb" => ProgramType::SkSkb,
90 "cgroup_device" => ProgramType::CgroupDevice,
91 "sk_msg" => ProgramType::SkMsg,
92 "raw_tracepoint" => ProgramType::RawTracepoint,
93 "cgroup_sock_addr" => ProgramType::CgroupSockAddr,
94 "lwt_seg6local" => ProgramType::LwtSeg6Local,
95 "lirc_mode2" => ProgramType::LircMode2,
96 "sk_reuseport" => ProgramType::SkReuseport,
97 "flow_dissector" => ProgramType::FlowDissector,
98 "cgroup_sysctl" => ProgramType::CgroupSysctl,
99 "raw_tracepoint_writable" => ProgramType::RawTracepointWritable,
100 "cgroup_sockopt" => ProgramType::CgroupSockopt,
101 "tracing" => ProgramType::Tracing,
102 "struct_ops" => ProgramType::StructOps,
103 "ext" => ProgramType::Ext,
104 "lsm" => ProgramType::Lsm,
105 "sk_lookup" => ProgramType::SkLookup,
106 "syscall" => ProgramType::Syscall,
107 other => {
108 return Err(ParseError::InvalidProgramType {
109 program: other.to_string(),
110 })
111 }
112 })
113 }
114}
115
116impl TryFrom<u32> for ProgramType {
117 type Error = ParseError;
118
119 fn try_from(value: u32) -> Result<Self, Self::Error> {
120 Ok(match value {
121 0 => ProgramType::Unspec,
122 1 => ProgramType::SocketFilter,
123 2 => ProgramType::Probe,
124 3 => ProgramType::Tc,
125 4 => ProgramType::SchedAct,
126 5 => ProgramType::Tracepoint,
127 6 => ProgramType::Xdp,
128 7 => ProgramType::PerfEvent,
129 8 => ProgramType::CgroupSkb,
130 9 => ProgramType::CgroupSock,
131 10 => ProgramType::LwtIn,
132 11 => ProgramType::LwtOut,
133 12 => ProgramType::LwtXmit,
134 13 => ProgramType::SockOps,
135 14 => ProgramType::SkSkb,
136 15 => ProgramType::CgroupDevice,
137 16 => ProgramType::SkMsg,
138 17 => ProgramType::RawTracepoint,
139 18 => ProgramType::CgroupSockAddr,
140 19 => ProgramType::LwtSeg6Local,
141 20 => ProgramType::LircMode2,
142 21 => ProgramType::SkReuseport,
143 22 => ProgramType::FlowDissector,
144 23 => ProgramType::CgroupSysctl,
145 24 => ProgramType::RawTracepointWritable,
146 25 => ProgramType::CgroupSockopt,
147 26 => ProgramType::Tracing,
148 27 => ProgramType::StructOps,
149 28 => ProgramType::Ext,
150 29 => ProgramType::Lsm,
151 30 => ProgramType::SkLookup,
152 31 => ProgramType::Syscall,
153 other => {
154 return Err(ParseError::InvalidProgramType {
155 program: other.to_string(),
156 })
157 }
158 })
159 }
160}
161
162impl std::fmt::Display for ProgramType {
163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164 let v = match self {
165 ProgramType::Unspec => "unspec",
166 ProgramType::SocketFilter => "socket_filter",
167 ProgramType::Probe => "probe",
168 ProgramType::Tc => "tc",
169 ProgramType::SchedAct => "sched_act",
170 ProgramType::Tracepoint => "tracepoint",
171 ProgramType::Xdp => "xdp",
172 ProgramType::PerfEvent => "perf_event",
173 ProgramType::CgroupSkb => "cgroup_skb",
174 ProgramType::CgroupSock => "cgroup_sock",
175 ProgramType::LwtIn => "lwt_in",
176 ProgramType::LwtOut => "lwt_out",
177 ProgramType::LwtXmit => "lwt_xmit",
178 ProgramType::SockOps => "sock_ops",
179 ProgramType::SkSkb => "sk_skb",
180 ProgramType::CgroupDevice => "cgroup_device",
181 ProgramType::SkMsg => "sk_msg",
182 ProgramType::RawTracepoint => "raw_tracepoint",
183 ProgramType::CgroupSockAddr => "cgroup_sock_addr",
184 ProgramType::LwtSeg6Local => "lwt_seg6local",
185 ProgramType::LircMode2 => "lirc_mode2",
186 ProgramType::SkReuseport => "sk_reuseport",
187 ProgramType::FlowDissector => "flow_dissector",
188 ProgramType::CgroupSysctl => "cgroup_sysctl",
189 ProgramType::RawTracepointWritable => "raw_tracepoint_writable",
190 ProgramType::CgroupSockopt => "cgroup_sockopt",
191 ProgramType::Tracing => "tracing",
192 ProgramType::StructOps => "struct_ops",
193 ProgramType::Ext => "ext",
194 ProgramType::Lsm => "lsm",
195 ProgramType::SkLookup => "sk_lookup",
196 ProgramType::Syscall => "syscall",
197 };
198 write!(f, "{v}")
199 }
200}
201
202#[derive(Copy, Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
203pub enum ProbeType {
204 Kprobe,
205 Kretprobe,
206 Uprobe,
207 Uretprobe,
208}
209
210impl TryFrom<i32> for ProbeType {
211 type Error = ParseError;
212
213 fn try_from(value: i32) -> Result<Self, Self::Error> {
214 Ok(match value {
215 0 => ProbeType::Kprobe,
216 1 => ProbeType::Kretprobe,
217 2 => ProbeType::Uprobe,
218 3 => ProbeType::Uretprobe,
219 other => {
220 return Err(ParseError::InvalidProbeType {
221 probe: other.to_string(),
222 })
223 }
224 })
225 }
226}
227
228impl From<aya::programs::ProbeKind> for ProbeType {
229 fn from(value: aya::programs::ProbeKind) -> Self {
230 match value {
231 aya::programs::ProbeKind::KProbe => ProbeType::Kprobe,
232 aya::programs::ProbeKind::KRetProbe => ProbeType::Kretprobe,
233 aya::programs::ProbeKind::UProbe => ProbeType::Uprobe,
234 aya::programs::ProbeKind::URetProbe => ProbeType::Uretprobe,
235 }
236 }
237}
238
239impl std::fmt::Display for ProbeType {
240 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
241 let v = match self {
242 ProbeType::Kprobe => "kprobe",
243 ProbeType::Kretprobe => "kretprobe",
244 ProbeType::Uprobe => "uprobe",
245 ProbeType::Uretprobe => "uretprobe",
246 };
247 write!(f, "{v}")
248 }
249}
250
251#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
252pub enum XdpProceedOnEntry {
253 Aborted,
254 Drop,
255 Pass,
256 Tx,
257 Redirect,
258 DispatcherReturn = 31,
259}
260
261impl TryFrom<String> for XdpProceedOnEntry {
262 type Error = ParseError;
263 fn try_from(value: String) -> Result<Self, Self::Error> {
264 Ok(match value.as_str() {
265 "aborted" => XdpProceedOnEntry::Aborted,
266 "drop" => XdpProceedOnEntry::Drop,
267 "pass" => XdpProceedOnEntry::Pass,
268 "tx" => XdpProceedOnEntry::Tx,
269 "redirect" => XdpProceedOnEntry::Redirect,
270 "dispatcher_return" => XdpProceedOnEntry::DispatcherReturn,
271 proceedon => {
272 return Err(ParseError::InvalidProceedOn {
273 proceedon: proceedon.to_string(),
274 })
275 }
276 })
277 }
278}
279
280impl TryFrom<i32> for XdpProceedOnEntry {
281 type Error = ParseError;
282 fn try_from(value: i32) -> Result<Self, Self::Error> {
283 Ok(match value {
284 0 => XdpProceedOnEntry::Aborted,
285 1 => XdpProceedOnEntry::Drop,
286 2 => XdpProceedOnEntry::Pass,
287 3 => XdpProceedOnEntry::Tx,
288 4 => XdpProceedOnEntry::Redirect,
289 31 => XdpProceedOnEntry::DispatcherReturn,
290 proceedon => {
291 return Err(ParseError::InvalidProceedOn {
292 proceedon: proceedon.to_string(),
293 })
294 }
295 })
296 }
297}
298
299impl std::fmt::Display for XdpProceedOnEntry {
300 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
301 let v = match self {
302 XdpProceedOnEntry::Aborted => "aborted",
303 XdpProceedOnEntry::Drop => "drop",
304 XdpProceedOnEntry::Pass => "pass",
305 XdpProceedOnEntry::Tx => "tx",
306 XdpProceedOnEntry::Redirect => "redirect",
307 XdpProceedOnEntry::DispatcherReturn => "dispatcher_return",
308 };
309 write!(f, "{v}")
310 }
311}
312
313#[derive(Serialize, Deserialize, Clone, Debug)]
314pub struct XdpProceedOn(Vec<XdpProceedOnEntry>);
315impl Default for XdpProceedOn {
316 fn default() -> Self {
317 XdpProceedOn(vec![
318 XdpProceedOnEntry::Pass,
319 XdpProceedOnEntry::DispatcherReturn,
320 ])
321 }
322}
323
324impl XdpProceedOn {
325 pub fn from_strings<T: AsRef<[String]>>(values: T) -> Result<XdpProceedOn, ParseError> {
326 let entries = values.as_ref();
327 let mut res = vec![];
328 for e in entries {
329 res.push(e.to_owned().try_into()?)
330 }
331 Ok(XdpProceedOn(res))
332 }
333
334 pub fn from_int32s<T: AsRef<[i32]>>(values: T) -> Result<XdpProceedOn, ParseError> {
335 let entries = values.as_ref();
336 if entries.is_empty() {
337 return Ok(XdpProceedOn::default());
338 }
339 let mut res = vec![];
340 for e in entries {
341 res.push((*e).try_into()?)
342 }
343 Ok(XdpProceedOn(res))
344 }
345
346 pub fn mask(&self) -> u32 {
347 let mut proceed_on_mask: u32 = 0;
348 for action in self.0.clone().into_iter() {
349 proceed_on_mask |= 1 << action as u32;
350 }
351 proceed_on_mask
352 }
353
354 pub fn as_action_vec(&self) -> Vec<i32> {
355 let mut res = vec![];
356 for entry in &self.0 {
357 res.push((*entry) as i32)
358 }
359 res
360 }
361}
362
363impl std::fmt::Display for XdpProceedOn {
364 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
365 let res: Vec<String> = self.0.iter().map(|x| x.to_string()).collect();
366 write!(f, "{}", res.join(", "))
367 }
368}
369
370#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
371pub enum TcProceedOnEntry {
372 Unspec = -1,
373 Ok = 0,
374 Reclassify,
375 Shot,
376 Pipe,
377 Stolen,
378 Queued,
379 Repeat,
380 Redirect,
381 Trap,
382 DispatcherReturn = 30,
383}
384
385impl TryFrom<String> for TcProceedOnEntry {
386 type Error = ParseError;
387 fn try_from(value: String) -> Result<Self, Self::Error> {
388 Ok(match value.as_str() {
389 "unspec" => TcProceedOnEntry::Unspec,
390 "ok" => TcProceedOnEntry::Ok,
391 "reclassify" => TcProceedOnEntry::Reclassify,
392 "shot" => TcProceedOnEntry::Shot,
393 "pipe" => TcProceedOnEntry::Pipe,
394 "stolen" => TcProceedOnEntry::Stolen,
395 "queued" => TcProceedOnEntry::Queued,
396 "repeat" => TcProceedOnEntry::Repeat,
397 "redirect" => TcProceedOnEntry::Redirect,
398 "trap" => TcProceedOnEntry::Trap,
399 "dispatcher_return" => TcProceedOnEntry::DispatcherReturn,
400 proceedon => {
401 return Err(ParseError::InvalidProceedOn {
402 proceedon: proceedon.to_string(),
403 })
404 }
405 })
406 }
407}
408
409impl TryFrom<i32> for TcProceedOnEntry {
410 type Error = ParseError;
411 fn try_from(value: i32) -> Result<Self, Self::Error> {
412 Ok(match value {
413 -1 => TcProceedOnEntry::Unspec,
414 0 => TcProceedOnEntry::Ok,
415 1 => TcProceedOnEntry::Reclassify,
416 2 => TcProceedOnEntry::Shot,
417 3 => TcProceedOnEntry::Pipe,
418 4 => TcProceedOnEntry::Stolen,
419 5 => TcProceedOnEntry::Queued,
420 6 => TcProceedOnEntry::Repeat,
421 7 => TcProceedOnEntry::Redirect,
422 8 => TcProceedOnEntry::Trap,
423 30 => TcProceedOnEntry::DispatcherReturn,
424 proceedon => {
425 return Err(ParseError::InvalidProceedOn {
426 proceedon: proceedon.to_string(),
427 })
428 }
429 })
430 }
431}
432
433impl std::fmt::Display for TcProceedOnEntry {
434 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
435 let v = match self {
436 TcProceedOnEntry::Unspec => "unspec",
437 TcProceedOnEntry::Ok => "ok",
438 TcProceedOnEntry::Reclassify => "reclassify",
439 TcProceedOnEntry::Shot => "shot",
440 TcProceedOnEntry::Pipe => "pipe",
441 TcProceedOnEntry::Stolen => "stolen",
442 TcProceedOnEntry::Queued => "queued",
443 TcProceedOnEntry::Repeat => "repeat",
444 TcProceedOnEntry::Redirect => "redirect",
445 TcProceedOnEntry::Trap => "trap",
446 TcProceedOnEntry::DispatcherReturn => "dispatcher_return",
447 };
448 write!(f, "{v}")
449 }
450}
451
452#[derive(Serialize, Deserialize, Clone, Debug)]
453pub struct TcProceedOn(pub(crate) Vec<TcProceedOnEntry>);
454impl Default for TcProceedOn {
455 fn default() -> Self {
456 TcProceedOn(vec![
457 TcProceedOnEntry::Pipe,
458 TcProceedOnEntry::DispatcherReturn,
459 ])
460 }
461}
462
463impl TcProceedOn {
464 pub fn from_strings<T: AsRef<[String]>>(values: T) -> Result<TcProceedOn, ParseError> {
465 let entries = values.as_ref();
466 let mut res = vec![];
467 for e in entries {
468 res.push(e.to_owned().try_into()?)
469 }
470 Ok(TcProceedOn(res))
471 }
472
473 pub fn from_int32s<T: AsRef<[i32]>>(values: T) -> Result<TcProceedOn, ParseError> {
474 let entries = values.as_ref();
475 if entries.is_empty() {
476 return Ok(TcProceedOn::default());
477 }
478 let mut res = vec![];
479 for e in entries {
480 res.push((*e).try_into()?)
481 }
482 Ok(TcProceedOn(res))
483 }
484
485 pub fn mask(&self) -> u32 {
490 let mut proceed_on_mask: u32 = 0;
491 for action in self.0.clone().into_iter() {
492 proceed_on_mask |= 1 << ((action as i32) + 1);
493 }
494 proceed_on_mask
495 }
496
497 pub fn as_action_vec(&self) -> Vec<i32> {
498 let mut res = vec![];
499 for entry in &self.0 {
500 res.push((*entry) as i32)
501 }
502 res
503 }
504}
505
506impl std::fmt::Display for TcProceedOn {
507 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
508 let res: Vec<String> = self.0.iter().map(|x| x.to_string()).collect();
509 write!(f, "{}", res.join(", "))
510 }
511}
512
513#[derive(Debug, Serialize, Deserialize, Clone)]
514pub enum ImagePullPolicy {
515 Always,
516 IfNotPresent,
517 Never,
518}
519
520impl std::fmt::Display for ImagePullPolicy {
521 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
522 let v = match self {
523 ImagePullPolicy::Always => "Always",
524 ImagePullPolicy::IfNotPresent => "IfNotPresent",
525 ImagePullPolicy::Never => "Never",
526 };
527 write!(f, "{v}")
528 }
529}
530
531impl TryFrom<i32> for ImagePullPolicy {
532 type Error = ParseError;
533 fn try_from(value: i32) -> Result<Self, Self::Error> {
534 Ok(match value {
535 0 => ImagePullPolicy::Always,
536 1 => ImagePullPolicy::IfNotPresent,
537 2 => ImagePullPolicy::Never,
538 policy => {
539 return Err(ParseError::InvalidBytecodeImagePullPolicy {
540 pull_policy: policy.to_string(),
541 })
542 }
543 })
544 }
545}
546
547impl TryFrom<&str> for ImagePullPolicy {
548 type Error = ParseError;
549 fn try_from(value: &str) -> Result<Self, Self::Error> {
550 Ok(match value {
551 "Always" => ImagePullPolicy::Always,
552 "IfNotPresent" => ImagePullPolicy::IfNotPresent,
553 "Never" => ImagePullPolicy::Never,
554 policy => {
555 return Err(ParseError::InvalidBytecodeImagePullPolicy {
556 pull_policy: policy.to_string(),
557 })
558 }
559 })
560 }
561}
562
563impl From<ImagePullPolicy> for i32 {
564 fn from(value: ImagePullPolicy) -> Self {
565 match value {
566 ImagePullPolicy::Always => 0,
567 ImagePullPolicy::IfNotPresent => 1,
568 ImagePullPolicy::Never => 2,
569 }
570 }
571}
572
573impl ToString for Location {
574 fn to_string(&self) -> String {
575 match &self {
576 Location::Image(i) => format!(
578 "image: {{ url: {}, pullpolicy: {} }}",
579 i.url,
580 TryInto::<ImagePullPolicy>::try_into(i.image_pull_policy).unwrap()
581 ),
582 Location::File(p) => format!("file: {{ path: {p} }}"),
583 }
584 }
585}