1use ebpf::{
6 CallingContext, CbpfConfig, CbpfLenInstruction, FieldDescriptor, FieldType, FunctionSignature,
7 HelperDefinition, MapSchema, MapTypeFilter, MemoryId, MemoryParameterSize, PointerOrigin,
8 StructDescriptor, Type,
9};
10use fidl_fuchsia_ebpf as febpf;
11use linux_uapi::{
12 __sk_buff, bpf_attach_type_BPF_CGROUP_DEVICE, bpf_attach_type_BPF_CGROUP_GETSOCKOPT,
13 bpf_attach_type_BPF_CGROUP_INET_EGRESS, bpf_attach_type_BPF_CGROUP_INET_INGRESS,
14 bpf_attach_type_BPF_CGROUP_INET_SOCK_CREATE, bpf_attach_type_BPF_CGROUP_INET_SOCK_RELEASE,
15 bpf_attach_type_BPF_CGROUP_INET4_BIND, bpf_attach_type_BPF_CGROUP_INET4_CONNECT,
16 bpf_attach_type_BPF_CGROUP_INET4_GETPEERNAME, bpf_attach_type_BPF_CGROUP_INET4_GETSOCKNAME,
17 bpf_attach_type_BPF_CGROUP_INET4_POST_BIND, bpf_attach_type_BPF_CGROUP_INET6_BIND,
18 bpf_attach_type_BPF_CGROUP_INET6_CONNECT, bpf_attach_type_BPF_CGROUP_INET6_GETPEERNAME,
19 bpf_attach_type_BPF_CGROUP_INET6_GETSOCKNAME, bpf_attach_type_BPF_CGROUP_INET6_POST_BIND,
20 bpf_attach_type_BPF_CGROUP_SETSOCKOPT, bpf_attach_type_BPF_CGROUP_SOCK_OPS,
21 bpf_attach_type_BPF_CGROUP_SYSCTL, bpf_attach_type_BPF_CGROUP_UDP4_RECVMSG,
22 bpf_attach_type_BPF_CGROUP_UDP4_SENDMSG, bpf_attach_type_BPF_CGROUP_UDP6_RECVMSG,
23 bpf_attach_type_BPF_CGROUP_UDP6_SENDMSG, bpf_attach_type_BPF_CGROUP_UNIX_CONNECT,
24 bpf_attach_type_BPF_CGROUP_UNIX_GETPEERNAME, bpf_attach_type_BPF_CGROUP_UNIX_GETSOCKNAME,
25 bpf_attach_type_BPF_CGROUP_UNIX_RECVMSG, bpf_attach_type_BPF_CGROUP_UNIX_SENDMSG,
26 bpf_attach_type_BPF_FLOW_DISSECTOR, bpf_attach_type_BPF_LIRC_MODE2,
27 bpf_attach_type_BPF_LSM_CGROUP, bpf_attach_type_BPF_LSM_MAC, bpf_attach_type_BPF_MODIFY_RETURN,
28 bpf_attach_type_BPF_NETFILTER, bpf_attach_type_BPF_NETKIT_PEER,
29 bpf_attach_type_BPF_NETKIT_PRIMARY, bpf_attach_type_BPF_PERF_EVENT,
30 bpf_attach_type_BPF_SK_LOOKUP, bpf_attach_type_BPF_SK_MSG_VERDICT,
31 bpf_attach_type_BPF_SK_REUSEPORT_SELECT, bpf_attach_type_BPF_SK_REUSEPORT_SELECT_OR_MIGRATE,
32 bpf_attach_type_BPF_SK_SKB_STREAM_PARSER, bpf_attach_type_BPF_SK_SKB_STREAM_VERDICT,
33 bpf_attach_type_BPF_SK_SKB_VERDICT, bpf_attach_type_BPF_STRUCT_OPS,
34 bpf_attach_type_BPF_TCX_EGRESS, bpf_attach_type_BPF_TCX_INGRESS,
35 bpf_attach_type_BPF_TRACE_FENTRY, bpf_attach_type_BPF_TRACE_FEXIT,
36 bpf_attach_type_BPF_TRACE_ITER, bpf_attach_type_BPF_TRACE_KPROBE_MULTI,
37 bpf_attach_type_BPF_TRACE_KPROBE_SESSION, bpf_attach_type_BPF_TRACE_RAW_TP,
38 bpf_attach_type_BPF_TRACE_UPROBE_MULTI, bpf_attach_type_BPF_XDP,
39 bpf_attach_type_BPF_XDP_CPUMAP, bpf_attach_type_BPF_XDP_DEVMAP,
40 bpf_func_id_BPF_FUNC_csum_update, bpf_func_id_BPF_FUNC_get_current_pid_tgid,
41 bpf_func_id_BPF_FUNC_get_current_uid_gid, bpf_func_id_BPF_FUNC_get_netns_cookie,
42 bpf_func_id_BPF_FUNC_get_retval, bpf_func_id_BPF_FUNC_get_smp_processor_id,
43 bpf_func_id_BPF_FUNC_get_socket_cookie, bpf_func_id_BPF_FUNC_get_socket_uid,
44 bpf_func_id_BPF_FUNC_ktime_get_boot_ns, bpf_func_id_BPF_FUNC_ktime_get_coarse_ns,
45 bpf_func_id_BPF_FUNC_ktime_get_ns, bpf_func_id_BPF_FUNC_l3_csum_replace,
46 bpf_func_id_BPF_FUNC_l4_csum_replace, bpf_func_id_BPF_FUNC_map_delete_elem,
47 bpf_func_id_BPF_FUNC_map_lookup_elem, bpf_func_id_BPF_FUNC_map_update_elem,
48 bpf_func_id_BPF_FUNC_probe_read_str, bpf_func_id_BPF_FUNC_probe_read_user,
49 bpf_func_id_BPF_FUNC_probe_read_user_str, bpf_func_id_BPF_FUNC_redirect,
50 bpf_func_id_BPF_FUNC_ringbuf_discard, bpf_func_id_BPF_FUNC_ringbuf_reserve,
51 bpf_func_id_BPF_FUNC_ringbuf_submit, bpf_func_id_BPF_FUNC_set_retval,
52 bpf_func_id_BPF_FUNC_sk_fullsock, bpf_func_id_BPF_FUNC_sk_lookup_tcp,
53 bpf_func_id_BPF_FUNC_sk_lookup_udp, bpf_func_id_BPF_FUNC_sk_release,
54 bpf_func_id_BPF_FUNC_sk_storage_get, bpf_func_id_BPF_FUNC_skb_adjust_room,
55 bpf_func_id_BPF_FUNC_skb_change_head, bpf_func_id_BPF_FUNC_skb_change_proto,
56 bpf_func_id_BPF_FUNC_skb_load_bytes, bpf_func_id_BPF_FUNC_skb_load_bytes_relative,
57 bpf_func_id_BPF_FUNC_skb_pull_data, bpf_func_id_BPF_FUNC_skb_store_bytes,
58 bpf_func_id_BPF_FUNC_trace_printk, bpf_map_type_BPF_MAP_TYPE_RINGBUF,
59 bpf_map_type_BPF_MAP_TYPE_SK_STORAGE, bpf_prog_type_BPF_PROG_TYPE_CGROUP_DEVICE,
60 bpf_prog_type_BPF_PROG_TYPE_CGROUP_SKB, bpf_prog_type_BPF_PROG_TYPE_CGROUP_SOCK,
61 bpf_prog_type_BPF_PROG_TYPE_CGROUP_SOCK_ADDR, bpf_prog_type_BPF_PROG_TYPE_CGROUP_SOCKOPT,
62 bpf_prog_type_BPF_PROG_TYPE_CGROUP_SYSCTL, bpf_prog_type_BPF_PROG_TYPE_EXT,
63 bpf_prog_type_BPF_PROG_TYPE_FLOW_DISSECTOR, bpf_prog_type_BPF_PROG_TYPE_KPROBE,
64 bpf_prog_type_BPF_PROG_TYPE_LIRC_MODE2, bpf_prog_type_BPF_PROG_TYPE_LSM,
65 bpf_prog_type_BPF_PROG_TYPE_LWT_IN, bpf_prog_type_BPF_PROG_TYPE_LWT_OUT,
66 bpf_prog_type_BPF_PROG_TYPE_LWT_SEG6LOCAL, bpf_prog_type_BPF_PROG_TYPE_LWT_XMIT,
67 bpf_prog_type_BPF_PROG_TYPE_NETFILTER, bpf_prog_type_BPF_PROG_TYPE_PERF_EVENT,
68 bpf_prog_type_BPF_PROG_TYPE_RAW_TRACEPOINT,
69 bpf_prog_type_BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE, bpf_prog_type_BPF_PROG_TYPE_SCHED_ACT,
70 bpf_prog_type_BPF_PROG_TYPE_SCHED_CLS, bpf_prog_type_BPF_PROG_TYPE_SK_LOOKUP,
71 bpf_prog_type_BPF_PROG_TYPE_SK_MSG, bpf_prog_type_BPF_PROG_TYPE_SK_REUSEPORT,
72 bpf_prog_type_BPF_PROG_TYPE_SK_SKB, bpf_prog_type_BPF_PROG_TYPE_SOCK_OPS,
73 bpf_prog_type_BPF_PROG_TYPE_SOCKET_FILTER, bpf_prog_type_BPF_PROG_TYPE_STRUCT_OPS,
74 bpf_prog_type_BPF_PROG_TYPE_SYSCALL, bpf_prog_type_BPF_PROG_TYPE_TRACEPOINT,
75 bpf_prog_type_BPF_PROG_TYPE_TRACING, bpf_prog_type_BPF_PROG_TYPE_UNSPEC,
76 bpf_prog_type_BPF_PROG_TYPE_XDP, bpf_sock, bpf_sock_addr, bpf_sockopt, bpf_user_pt_regs_t,
77 seccomp_data, xdp_md,
78};
79use std::collections::HashMap;
80use std::mem::{offset_of, size_of};
81use std::sync::{Arc, LazyLock};
82use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
83
84#[derive(Clone, Default, Debug)]
85pub struct BpfTypeFilter(Vec<ProgramType>);
86
87impl<T: IntoIterator<Item = ProgramType>> From<T> for BpfTypeFilter {
88 fn from(types: T) -> Self {
89 Self(types.into_iter().collect())
90 }
91}
92
93impl BpfTypeFilter {
94 pub fn accept(&self, program_type: ProgramType) -> bool {
95 self.0.is_empty() || self.0.iter().find(|v| **v == program_type).is_some()
96 }
97}
98
99static SPECIAL_MAP_TYPES: &[linux_uapi::bpf_map_type] =
102 &[bpf_map_type_BPF_MAP_TYPE_SK_STORAGE, bpf_map_type_BPF_MAP_TYPE_RINGBUF];
103
104static BPF_HELPERS_DEFINITIONS: LazyLock<Vec<(BpfTypeFilter, HelperDefinition)>> =
105 LazyLock::new(|| {
106 vec![
107 (
108 BpfTypeFilter::default(),
109 HelperDefinition {
110 index: bpf_func_id_BPF_FUNC_map_lookup_elem,
111 name: "map_lookup_elem",
112 signature: FunctionSignature {
113 args: vec![
114 Type::ConstPtrToMapParameter {
115 filter: MapTypeFilter::DenyList(SPECIAL_MAP_TYPES),
116 must_be_writable: false,
117 },
118 Type::MapKeyParameter { map_ptr_index: 0 },
119 ],
120 return_value: Type::NullOrParameter(Box::new(Type::MapValueParameter {
121 map_ptr_index: 0,
122 })),
123 invalidate_array_bounds: false,
124 },
125 },
126 ),
127 (
128 BpfTypeFilter::default(),
129 HelperDefinition {
130 index: bpf_func_id_BPF_FUNC_map_update_elem,
131 name: "map_update_elem",
132 signature: FunctionSignature {
133 args: vec![
134 Type::ConstPtrToMapParameter {
135 filter: MapTypeFilter::DenyList(SPECIAL_MAP_TYPES),
136 must_be_writable: true,
137 },
138 Type::MapKeyParameter { map_ptr_index: 0 },
139 Type::MapValueParameter { map_ptr_index: 0 },
140 Type::ScalarValueParameter,
141 ],
142 return_value: Type::UNKNOWN_SCALAR,
143 invalidate_array_bounds: false,
144 },
145 },
146 ),
147 (
148 BpfTypeFilter::default(),
149 HelperDefinition {
150 index: bpf_func_id_BPF_FUNC_map_delete_elem,
151 name: "map_delete_elem",
152 signature: FunctionSignature {
153 args: vec![
154 Type::ConstPtrToMapParameter {
155 filter: MapTypeFilter::DenyList(SPECIAL_MAP_TYPES),
156 must_be_writable: true,
157 },
158 Type::MapKeyParameter { map_ptr_index: 0 },
159 ],
160 return_value: Type::UNKNOWN_SCALAR,
161 invalidate_array_bounds: false,
162 },
163 },
164 ),
165 (
166 BpfTypeFilter::default(),
167 HelperDefinition {
168 index: bpf_func_id_BPF_FUNC_trace_printk,
169 name: "trace_printk",
170 signature: FunctionSignature {
171 args: vec![],
173 return_value: Type::UNKNOWN_SCALAR,
174 invalidate_array_bounds: false,
175 },
176 },
177 ),
178 (
179 BpfTypeFilter::default(),
180 HelperDefinition {
181 index: bpf_func_id_BPF_FUNC_ktime_get_ns,
182 name: "ktime_get_ns",
183 signature: FunctionSignature {
184 args: vec![],
185 return_value: Type::UNKNOWN_SCALAR,
186 invalidate_array_bounds: false,
187 },
188 },
189 ),
190 (
191 BpfTypeFilter::default(),
192 HelperDefinition {
193 index: bpf_func_id_BPF_FUNC_probe_read_user,
194 name: "probe_read_user",
195 signature: FunctionSignature {
196 args: vec![
197 Type::MemoryParameter {
198 size: MemoryParameterSize::Reference { index: 1 },
199 input: false,
200 output: true,
201 },
202 Type::ScalarValueParameter,
203 Type::AnyParameter,
204 ],
205 return_value: Type::UNKNOWN_SCALAR,
206 invalidate_array_bounds: false,
207 },
208 },
209 ),
210 (
211 BpfTypeFilter::default(),
212 HelperDefinition {
213 index: bpf_func_id_BPF_FUNC_probe_read_user_str,
214 name: "probe_read_user_str",
215 signature: FunctionSignature {
216 args: vec![
217 Type::MemoryParameter {
218 size: MemoryParameterSize::Reference { index: 1 },
219 input: false,
220 output: true,
221 },
222 Type::ScalarValueParameter,
223 Type::ScalarValueParameter,
224 ],
225 return_value: Type::UNKNOWN_SCALAR,
226 invalidate_array_bounds: false,
227 },
228 },
229 ),
230 (
231 vec![
232 ProgramType::CgroupSkb,
233 ProgramType::SchedAct,
234 ProgramType::SchedCls,
235 ProgramType::SocketFilter,
236 ]
237 .into(),
238 HelperDefinition {
239 index: bpf_func_id_BPF_FUNC_get_socket_uid,
240 name: "get_socket_uid",
241 signature: FunctionSignature {
242 args: vec![Type::StructParameter { id: SK_BUF_ID.clone() }],
243 return_value: Type::UNKNOWN_SCALAR,
244 invalidate_array_bounds: false,
245 },
246 },
247 ),
248 (
249 vec![
250 ProgramType::CgroupSock,
251 ProgramType::CgroupSockAddr,
252 ProgramType::CgroupSockopt,
253 ProgramType::Kprobe,
254 ProgramType::Tracepoint,
255 ]
256 .into(),
257 HelperDefinition {
258 index: bpf_func_id_BPF_FUNC_get_current_uid_gid,
259 name: "get_current_uid_gid",
260 signature: FunctionSignature {
261 args: vec![],
262 return_value: Type::UNKNOWN_SCALAR,
263 invalidate_array_bounds: false,
264 },
265 },
266 ),
267 (
268 vec![
269 ProgramType::CgroupSock,
270 ProgramType::CgroupSockAddr,
271 ProgramType::CgroupSockopt,
272 ProgramType::Kprobe,
273 ProgramType::Tracepoint,
274 ]
275 .into(),
276 HelperDefinition {
277 index: bpf_func_id_BPF_FUNC_get_current_pid_tgid,
278 name: "get_current_pid_tgid",
279 signature: FunctionSignature {
280 args: vec![],
281 return_value: Type::UNKNOWN_SCALAR,
282 invalidate_array_bounds: false,
283 },
284 },
285 ),
286 (
287 vec![ProgramType::SchedAct, ProgramType::SchedCls].into(),
288 HelperDefinition {
289 index: bpf_func_id_BPF_FUNC_skb_pull_data,
290 name: "skb_pull_data",
291 signature: FunctionSignature {
292 args: vec![
293 Type::StructParameter { id: SK_BUF_ID.clone() },
294 Type::ScalarValueParameter,
295 ],
296 return_value: Type::UNKNOWN_SCALAR,
297 invalidate_array_bounds: true,
298 },
299 },
300 ),
301 (
302 BpfTypeFilter::default(),
303 HelperDefinition {
304 index: bpf_func_id_BPF_FUNC_ringbuf_reserve,
305 name: "ringbuf_reserve",
306 signature: FunctionSignature {
307 args: vec![
308 Type::ConstPtrToMapParameter {
309 filter: MapTypeFilter::AllowList(&[
310 bpf_map_type_BPF_MAP_TYPE_RINGBUF,
311 ]),
312 must_be_writable: true,
313 },
314 Type::ScalarValueParameter,
315 Type::ScalarValueParameter,
316 ],
317 return_value: Type::NullOrParameter(Box::new(Type::ReleasableParameter {
318 id: RING_BUFFER_RESERVATION.clone(),
319 inner: Box::new(Type::MemoryParameter {
320 size: MemoryParameterSize::Reference { index: 1 },
321 input: false,
322 output: false,
323 }),
324 })),
325 invalidate_array_bounds: false,
326 },
327 },
328 ),
329 (
330 BpfTypeFilter::default(),
331 HelperDefinition {
332 index: bpf_func_id_BPF_FUNC_ringbuf_submit,
333 name: "ringbuf_submit",
334 signature: FunctionSignature {
335 args: vec![
336 Type::ReleaseParameter { id: RING_BUFFER_RESERVATION.clone() },
337 Type::ScalarValueParameter,
338 ],
339 return_value: Type::default(),
340 invalidate_array_bounds: false,
341 },
342 },
343 ),
344 (
345 BpfTypeFilter::default(),
346 HelperDefinition {
347 index: bpf_func_id_BPF_FUNC_ringbuf_discard,
348 name: "ringbuf_discard",
349 signature: FunctionSignature {
350 args: vec![
351 Type::ReleaseParameter { id: RING_BUFFER_RESERVATION.clone() },
352 Type::ScalarValueParameter,
353 ],
354 return_value: Type::default(),
355 invalidate_array_bounds: false,
356 },
357 },
358 ),
359 (
360 vec![ProgramType::SchedAct, ProgramType::SchedCls].into(),
361 HelperDefinition {
362 index: bpf_func_id_BPF_FUNC_skb_change_proto,
363 name: "skb_change_proto",
364 signature: FunctionSignature {
365 args: vec![
366 Type::StructParameter { id: SK_BUF_ID.clone() },
367 Type::ScalarValueParameter,
368 Type::ScalarValueParameter,
369 ],
370 return_value: Type::UNKNOWN_SCALAR,
371 invalidate_array_bounds: true,
372 },
373 },
374 ),
375 (
376 vec![ProgramType::SchedAct, ProgramType::SchedCls].into(),
377 HelperDefinition {
378 index: bpf_func_id_BPF_FUNC_csum_update,
379 name: "csum_update",
380 signature: FunctionSignature {
381 args: vec![
382 Type::StructParameter { id: SK_BUF_ID.clone() },
383 Type::ScalarValueParameter,
384 ],
385 return_value: Type::UNKNOWN_SCALAR,
386 invalidate_array_bounds: false,
387 },
388 },
389 ),
390 (
391 vec![ProgramType::Kprobe, ProgramType::Tracepoint].into(),
392 HelperDefinition {
393 index: bpf_func_id_BPF_FUNC_probe_read_str,
394 name: "probe_read_str",
395 signature: FunctionSignature {
396 args: vec![],
398 return_value: Type::UNKNOWN_SCALAR,
399 invalidate_array_bounds: false,
400 },
401 },
402 ),
403 (
404 vec![
405 ProgramType::CgroupSkb,
406 ProgramType::SchedAct,
407 ProgramType::SchedCls,
408 ProgramType::SocketFilter,
409 ProgramType::CgroupSock,
410 ProgramType::CgroupSockAddr,
411 ]
412 .into(),
413 HelperDefinition {
414 index: bpf_func_id_BPF_FUNC_get_socket_cookie,
415 name: "get_socket_cookie",
416 signature: FunctionSignature {
417 args: vec![Type::ContextParameter { parameter_index: 0 }],
418 return_value: Type::UNKNOWN_SCALAR,
419 invalidate_array_bounds: false,
420 },
421 },
422 ),
423 (
424 vec![ProgramType::SchedAct, ProgramType::SchedCls].into(),
425 HelperDefinition {
426 index: bpf_func_id_BPF_FUNC_redirect,
427 name: "redirect",
428 signature: FunctionSignature {
429 args: vec![Type::ScalarValueParameter, Type::ScalarValueParameter],
430 return_value: Type::UNKNOWN_SCALAR,
431 invalidate_array_bounds: false,
432 },
433 },
434 ),
435 (
436 vec![ProgramType::SchedAct, ProgramType::SchedCls].into(),
437 HelperDefinition {
438 index: bpf_func_id_BPF_FUNC_skb_adjust_room,
439 name: "skb_adjust_room",
440 signature: FunctionSignature {
441 args: vec![
442 Type::StructParameter { id: SK_BUF_ID.clone() },
443 Type::ScalarValueParameter,
444 Type::ScalarValueParameter,
445 Type::ScalarValueParameter,
446 ],
447 return_value: Type::UNKNOWN_SCALAR,
448 invalidate_array_bounds: true,
449 },
450 },
451 ),
452 (
453 vec![ProgramType::SchedAct, ProgramType::SchedCls].into(),
454 HelperDefinition {
455 index: bpf_func_id_BPF_FUNC_l3_csum_replace,
456 name: "l3_csum_replace",
457 signature: FunctionSignature {
458 args: vec![
459 Type::StructParameter { id: SK_BUF_ID.clone() },
460 Type::ScalarValueParameter,
461 Type::ScalarValueParameter,
462 Type::ScalarValueParameter,
463 Type::ScalarValueParameter,
464 ],
465 return_value: Type::UNKNOWN_SCALAR,
466 invalidate_array_bounds: true,
467 },
468 },
469 ),
470 (
471 vec![ProgramType::SchedAct, ProgramType::SchedCls].into(),
472 HelperDefinition {
473 index: bpf_func_id_BPF_FUNC_l4_csum_replace,
474 name: "l4_csum_replace",
475 signature: FunctionSignature {
476 args: vec![
477 Type::StructParameter { id: SK_BUF_ID.clone() },
478 Type::ScalarValueParameter,
479 Type::ScalarValueParameter,
480 Type::ScalarValueParameter,
481 Type::ScalarValueParameter,
482 ],
483 return_value: Type::UNKNOWN_SCALAR,
484 invalidate_array_bounds: true,
485 },
486 },
487 ),
488 (
489 vec![ProgramType::SchedAct, ProgramType::SchedCls].into(),
490 HelperDefinition {
491 index: bpf_func_id_BPF_FUNC_skb_store_bytes,
492 name: "skb_store_bytes",
493 signature: FunctionSignature {
494 args: vec![
495 Type::StructParameter { id: SK_BUF_ID.clone() },
496 Type::ScalarValueParameter,
497 Type::MemoryParameter {
498 size: MemoryParameterSize::Reference { index: 3 },
499 input: true,
500 output: false,
501 },
502 Type::ScalarValueParameter,
503 Type::ScalarValueParameter,
504 ],
505 return_value: Type::UNKNOWN_SCALAR,
506 invalidate_array_bounds: true,
507 },
508 },
509 ),
510 (
511 vec![ProgramType::SchedAct, ProgramType::SchedCls].into(),
512 HelperDefinition {
513 index: bpf_func_id_BPF_FUNC_skb_change_head,
514 name: "skb_change_head",
515 signature: FunctionSignature {
516 args: vec![
517 Type::StructParameter { id: SK_BUF_ID.clone() },
518 Type::ScalarValueParameter,
519 Type::ScalarValueParameter,
520 ],
521 return_value: Type::UNKNOWN_SCALAR,
522 invalidate_array_bounds: true,
523 },
524 },
525 ),
526 (
527 vec![
528 ProgramType::CgroupSkb,
529 ProgramType::SchedAct,
530 ProgramType::SchedCls,
531 ProgramType::SocketFilter,
532 ]
533 .into(),
534 HelperDefinition {
535 index: bpf_func_id_BPF_FUNC_skb_load_bytes,
536 name: "skb_load_bytes",
537 signature: FunctionSignature {
538 args: vec![
539 Type::StructParameter { id: SK_BUF_ID.clone() },
540 Type::ScalarValueParameter,
541 Type::MemoryParameter {
542 size: MemoryParameterSize::Reference { index: 3 },
543 input: false,
544 output: true,
545 },
546 Type::ScalarValueParameter,
547 ],
548 return_value: Type::UNKNOWN_SCALAR,
549 invalidate_array_bounds: false,
550 },
551 },
552 ),
553 (
554 vec![
555 ProgramType::CgroupSkb,
556 ProgramType::SchedAct,
557 ProgramType::SchedCls,
558 ProgramType::SocketFilter,
559 ]
560 .into(),
561 HelperDefinition {
562 index: bpf_func_id_BPF_FUNC_skb_load_bytes_relative,
563 name: "skb_load_bytes_relative",
564 signature: FunctionSignature {
565 args: vec![
566 Type::StructParameter { id: SK_BUF_ID.clone() },
567 Type::ScalarValueParameter,
568 Type::MemoryParameter {
569 size: MemoryParameterSize::Reference { index: 3 },
570 input: false,
571 output: true,
572 },
573 Type::ScalarValueParameter,
574 Type::ScalarValueParameter,
575 ],
576 return_value: Type::UNKNOWN_SCALAR,
577 invalidate_array_bounds: false,
578 },
579 },
580 ),
581 (
582 BpfTypeFilter::default(),
583 HelperDefinition {
584 index: bpf_func_id_BPF_FUNC_ktime_get_boot_ns,
585 name: "ktime_get_boot_ns",
586 signature: FunctionSignature {
587 args: vec![],
588 return_value: Type::UNKNOWN_SCALAR,
589 invalidate_array_bounds: false,
590 },
591 },
592 ),
593 (
594 BpfTypeFilter::default(),
595 HelperDefinition {
596 index: bpf_func_id_BPF_FUNC_ktime_get_coarse_ns,
597 name: "ktime_get_coarse_ns",
598 signature: FunctionSignature {
599 args: vec![],
600 return_value: Type::UNKNOWN_SCALAR,
601 invalidate_array_bounds: false,
602 },
603 },
604 ),
605 (
606 vec![
607 ProgramType::CgroupSkb,
608 ProgramType::CgroupSock,
609 ProgramType::CgroupSockopt,
610 ProgramType::CgroupSockAddr,
611 ]
612 .into(),
613 HelperDefinition {
614 index: bpf_func_id_BPF_FUNC_sk_storage_get,
615 name: "sk_storage_get",
616 signature: FunctionSignature {
617 args: vec![
618 Type::ConstPtrToMapParameter {
619 filter: MapTypeFilter::AllowList(&[
620 bpf_map_type_BPF_MAP_TYPE_SK_STORAGE,
621 ]),
622 must_be_writable: false,
623 },
624 Type::StructParameter { id: BPF_SOCK_ID.clone() },
625 Type::NullOrParameter(Box::new(Type::MapValueParameter {
626 map_ptr_index: 0,
627 })),
628 Type::ScalarValueParameter,
629 ],
630 return_value: Type::NullOrParameter(Box::new(Type::MapValueParameter {
631 map_ptr_index: 0,
632 })),
633 invalidate_array_bounds: false,
634 },
635 },
636 ),
637 (
638 BpfTypeFilter::default(),
639 HelperDefinition {
640 index: bpf_func_id_BPF_FUNC_get_smp_processor_id,
641 name: "get_smp_processor_id",
642 signature: FunctionSignature {
643 args: vec![],
644 return_value: Type::UNKNOWN_SCALAR,
645 invalidate_array_bounds: false,
646 },
647 },
648 ),
649 (
650 vec![ProgramType::CgroupSkb, ProgramType::SchedAct, ProgramType::SchedCls].into(),
651 HelperDefinition {
652 index: bpf_func_id_BPF_FUNC_sk_fullsock,
653 name: "sk_fullsock",
654 signature: FunctionSignature {
655 args: vec![Type::StructParameter { id: BPF_SOCK_ID.clone() }],
656 return_value: Type::NullOrParameter(Box::new(ptr_to_mem_type::<bpf_sock>(
657 BPF_SOCK_ID.clone(),
658 ))),
659 invalidate_array_bounds: false,
660 },
661 },
662 ),
663 (
664 vec![
665 ProgramType::CgroupDevice,
666 ProgramType::CgroupSockopt,
667 ProgramType::CgroupSysctl,
668 ]
669 .into(),
670 HelperDefinition {
671 index: bpf_func_id_BPF_FUNC_set_retval,
672 name: "set_retval",
673 signature: FunctionSignature {
674 args: vec![Type::ScalarValueParameter],
675 return_value: Type::UNKNOWN_SCALAR,
676 invalidate_array_bounds: false,
677 },
678 },
679 ),
680 (
681 vec![
682 ProgramType::CgroupDevice,
683 ProgramType::CgroupSockopt,
684 ProgramType::CgroupSysctl,
685 ]
686 .into(),
687 HelperDefinition {
688 index: bpf_func_id_BPF_FUNC_get_retval,
689 name: "get_retval",
690 signature: FunctionSignature {
691 args: vec![],
692 return_value: Type::UNKNOWN_SCALAR,
693 invalidate_array_bounds: false,
694 },
695 },
696 ),
697 (
698 vec![
701 ProgramType::CgroupSkb,
702 ProgramType::SchedAct,
703 ProgramType::SchedCls,
704 ProgramType::SkSkb,
705 ]
706 .into(),
707 HelperDefinition {
708 index: bpf_func_id_BPF_FUNC_sk_lookup_tcp,
709 name: "sk_lookup_tcp",
710 signature: FunctionSignature {
711 args: vec![
712 Type::StructParameter { id: SK_BUF_ID.clone() },
713 Type::MemoryParameter {
714 size: MemoryParameterSize::Reference { index: 2 },
715 input: true,
716 output: false,
717 },
718 Type::ScalarValueParameter,
719 Type::ScalarValueParameter,
720 Type::ScalarValueParameter,
721 ],
722 return_value: Type::NullOrParameter(Box::new(Type::ReleasableParameter {
723 id: RELEASABLE_BPF_SOCK_PTR.clone(),
724 inner: Box::new(BPF_SOCK_TYPE.clone()),
725 })),
726 invalidate_array_bounds: false,
727 },
728 },
729 ),
730 (
731 vec![
734 ProgramType::CgroupSkb,
735 ProgramType::SchedAct,
736 ProgramType::SchedCls,
737 ProgramType::SkSkb,
738 ]
739 .into(),
740 HelperDefinition {
741 index: bpf_func_id_BPF_FUNC_sk_lookup_udp,
742 name: "sk_lookup_udp",
743 signature: FunctionSignature {
744 args: vec![
745 Type::StructParameter { id: SK_BUF_ID.clone() },
746 Type::MemoryParameter {
747 size: MemoryParameterSize::Reference { index: 2 },
748 input: true,
749 output: false,
750 },
751 Type::ScalarValueParameter,
752 Type::ScalarValueParameter,
753 Type::ScalarValueParameter,
754 ],
755 return_value: Type::NullOrParameter(Box::new(Type::ReleasableParameter {
756 id: RELEASABLE_BPF_SOCK_PTR.clone(),
757 inner: Box::new(BPF_SOCK_TYPE.clone()),
758 })),
759 invalidate_array_bounds: false,
760 },
761 },
762 ),
763 (
764 vec![
765 ProgramType::CgroupSkb,
766 ProgramType::CgroupSockAddr,
767 ProgramType::SchedAct,
768 ProgramType::SchedCls,
769 ProgramType::SkSkb,
770 ProgramType::Xdp,
771 ]
772 .into(),
773 HelperDefinition {
774 index: bpf_func_id_BPF_FUNC_sk_release,
775 name: "sk_release",
776 signature: FunctionSignature {
777 args: vec![Type::ReleaseParameter { id: RELEASABLE_BPF_SOCK_PTR.clone() }],
778 return_value: Type::UNKNOWN_SCALAR,
779 invalidate_array_bounds: false,
780 },
781 },
782 ),
783 (
784 vec![
785 ProgramType::CgroupSkb,
786 ProgramType::CgroupSock,
787 ProgramType::CgroupSockopt,
788 ProgramType::CgroupSockAddr,
789 ProgramType::SchedAct,
790 ProgramType::SchedCls,
791 ProgramType::SkMsg,
792 ProgramType::SocketFilter,
793 ProgramType::SockOps,
794 ]
795 .into(),
796 HelperDefinition {
797 index: bpf_func_id_BPF_FUNC_get_netns_cookie,
798 name: "bpf_get_netns_cookie",
799 signature: FunctionSignature {
800 args: vec![Type::NullOrParameter(Box::new(Type::ContextParameter {
801 parameter_index: 0,
802 }))],
803 return_value: Type::UNKNOWN_SCALAR,
804 invalidate_array_bounds: false,
805 },
806 },
807 ),
808 ]
809 });
810
811#[derive(Copy, Clone, Debug, PartialEq, Eq)]
813pub enum StructId {
814 SkBuff = 1,
815 XdpMd = 2,
816 BpfUserPtRegs = 3,
817 BpfSock = 4,
818 BpfSockOpt = 5,
819 BpfSockAddr = 6,
820}
821
822impl StructId {
823 pub const fn as_memory_id(self) -> MemoryId {
824 MemoryId::from_raw(self as u64)
825 }
826}
827
828impl From<StructId> for febpf::StructId {
829 fn from(value: StructId) -> Self {
830 match value {
831 StructId::SkBuff => febpf::StructId::SkBuff,
832 StructId::XdpMd => febpf::StructId::XdpMd,
833 StructId::BpfUserPtRegs => febpf::StructId::BpfUserPtRegs,
834 StructId::BpfSock => febpf::StructId::BpfSock,
835 StructId::BpfSockOpt => febpf::StructId::BpfSockOpt,
836 StructId::BpfSockAddr => febpf::StructId::BpfSockAddr,
837 }
838 }
839}
840
841impl TryFrom<&MemoryId> for StructId {
842 type Error = ();
843
844 fn try_from(value: &MemoryId) -> Result<Self, Self::Error> {
845 if *value == StructId::SkBuff.as_memory_id() {
846 Ok(StructId::SkBuff)
847 } else if *value == StructId::XdpMd.as_memory_id() {
848 Ok(StructId::XdpMd)
849 } else if *value == StructId::BpfUserPtRegs.as_memory_id() {
850 Ok(StructId::BpfUserPtRegs)
851 } else if *value == StructId::BpfSock.as_memory_id() {
852 Ok(StructId::BpfSock)
853 } else if *value == StructId::BpfSockOpt.as_memory_id() {
854 Ok(StructId::BpfSockOpt)
855 } else if *value == StructId::BpfSockAddr.as_memory_id() {
856 Ok(StructId::BpfSockAddr)
857 } else {
858 Err(())
859 }
860 }
861}
862
863impl From<febpf::StructId> for StructId {
864 fn from(value: febpf::StructId) -> Self {
865 match value {
866 febpf::StructId::SkBuff => StructId::SkBuff,
867 febpf::StructId::XdpMd => StructId::XdpMd,
868 febpf::StructId::BpfUserPtRegs => StructId::BpfUserPtRegs,
869 febpf::StructId::BpfSock => StructId::BpfSock,
870 febpf::StructId::BpfSockOpt => StructId::BpfSockOpt,
871 febpf::StructId::BpfSockAddr => StructId::BpfSockAddr,
872 febpf::StructId::__SourceBreaking { unknown_ordinal } => {
873 panic!("Invalid struct id: {}", unknown_ordinal)
874 }
875 }
876 }
877}
878
879fn scalar_field(offset: usize, size: usize) -> FieldDescriptor {
880 FieldDescriptor { offset, field_type: FieldType::Scalar { size } }
881}
882
883fn scalar_range(offset: usize, end_offset: usize) -> FieldDescriptor {
884 FieldDescriptor { offset, field_type: FieldType::Scalar { size: end_offset - offset } }
885}
886
887fn scalar_mut_range(offset: usize, end_offset: usize) -> FieldDescriptor {
888 FieldDescriptor { offset, field_type: FieldType::MutableScalar { size: end_offset - offset } }
889}
890
891fn scalar_u32_field(offset: usize) -> FieldDescriptor {
892 FieldDescriptor { offset, field_type: FieldType::Scalar { size: std::mem::size_of::<u32>() } }
893}
894
895fn scalar_u32_mut_field(offset: usize) -> FieldDescriptor {
896 FieldDescriptor {
897 offset,
898 field_type: FieldType::MutableScalar { size: std::mem::size_of::<u32>() },
899 }
900}
901
902fn scalar_u64_field(offset: usize) -> FieldDescriptor {
903 FieldDescriptor { offset, field_type: FieldType::Scalar { size: std::mem::size_of::<u64>() } }
904}
905
906fn array_start_field(offset: usize, id: MemoryId) -> FieldDescriptor {
907 FieldDescriptor { offset, field_type: FieldType::PtrToArray { id, is_32_bit: false } }
908}
909
910fn array_end_field(offset: usize, id: MemoryId) -> FieldDescriptor {
911 FieldDescriptor { offset, field_type: FieldType::PtrToEndArray { id, is_32_bit: false } }
912}
913
914fn array_start_32_field(offset: usize, id: MemoryId) -> FieldDescriptor {
915 FieldDescriptor { offset, field_type: FieldType::PtrToArray { id, is_32_bit: true } }
916}
917
918fn array_end_32_field(offset: usize, id: MemoryId) -> FieldDescriptor {
919 FieldDescriptor { offset, field_type: FieldType::PtrToEndArray { id, is_32_bit: true } }
920}
921
922fn ptr_to_mem_field<T: IntoBytes>(offset: usize, id: MemoryId) -> FieldDescriptor {
923 FieldDescriptor {
924 offset,
925 field_type: FieldType::PtrToMemory {
926 id,
927 buffer_size: std::mem::size_of::<T>(),
928 is_32_bit: false,
929 },
930 }
931}
932
933fn nullable_ptr_to_mem_field<T: IntoBytes>(offset: usize, id: MemoryId) -> FieldDescriptor {
934 FieldDescriptor {
935 offset,
936 field_type: FieldType::NullablePtrToMemory {
937 is_32_bit: false,
938 id,
939 buffer_size: std::mem::size_of::<T>(),
940 },
941 }
942}
943
944fn ptr_to_struct_type(id: MemoryId, fields: Vec<FieldDescriptor>) -> Type {
945 Type::PtrToStruct { id, offset: 0.into(), descriptor: Arc::new(StructDescriptor { fields }) }
946}
947
948fn ptr_to_mem_type<T: IntoBytes>(id: MemoryId) -> Type {
949 Type::PtrToMemory {
950 id,
951 offset: 0.into(),
952 buffer_size: std::mem::size_of::<T>() as u64,
953 origin: PointerOrigin::KernelReadOnly,
954 }
955}
956
957static RING_BUFFER_RESERVATION: LazyLock<MemoryId> = LazyLock::new(MemoryId::new);
958
959static RELEASABLE_BPF_SOCK_PTR: LazyLock<MemoryId> = LazyLock::new(MemoryId::new);
962
963pub static SK_BUF_ID: MemoryId = StructId::SkBuff.as_memory_id();
964
965pub static SOCKET_FILTER_SK_BUF_TYPE: LazyLock<Type> = LazyLock::new(|| {
967 ptr_to_struct_type(
968 SK_BUF_ID.clone(),
969 vec![
970 scalar_range(0, offset_of!(__sk_buff, cb)),
972 scalar_mut_range(offset_of!(__sk_buff, cb), offset_of!(__sk_buff, hash)),
974 scalar_u32_field(offset_of!(__sk_buff, hash)),
975 scalar_u32_field(offset_of!(__sk_buff, napi_id)),
976 scalar_u32_field(offset_of!(__sk_buff, tstamp)),
977 scalar_u32_field(offset_of!(__sk_buff, gso_segs)),
978 scalar_u32_field(offset_of!(__sk_buff, gso_size)),
979 ],
980 )
981});
982pub static SOCKET_FILTER_ARGS: LazyLock<Vec<Type>> =
983 LazyLock::new(|| vec![SOCKET_FILTER_SK_BUF_TYPE.clone()]);
984
985pub static SCHED_ARG_TYPE: LazyLock<Type> = LazyLock::new(|| {
988 let data_id = MemoryId::new();
989 ptr_to_struct_type(
990 SK_BUF_ID.clone(),
991 vec![
992 scalar_range(0, offset_of!(__sk_buff, mark)),
995 scalar_u32_mut_field(offset_of!(__sk_buff, mark)),
996 scalar_range(offset_of!(__sk_buff, queue_mapping), offset_of!(__sk_buff, cb)),
997 scalar_mut_range(offset_of!(__sk_buff, cb), offset_of!(__sk_buff, hash)),
999 scalar_u32_field(offset_of!(__sk_buff, hash)),
1000 scalar_u32_field(offset_of!(__sk_buff, tc_classid)),
1001 array_start_32_field(offset_of!(__sk_buff, data), data_id.clone()),
1002 array_end_32_field(offset_of!(__sk_buff, data_end), data_id),
1003 scalar_u32_field(offset_of!(__sk_buff, napi_id)),
1004 scalar_u32_field(offset_of!(__sk_buff, data_meta)),
1005 scalar_range(offset_of!(__sk_buff, tstamp), size_of::<__sk_buff>()),
1006 ],
1007 )
1008});
1009pub static SCHED_ARGS: LazyLock<Vec<Type>> = LazyLock::new(|| vec![SCHED_ARG_TYPE.clone()]);
1010
1011pub static CGROUP_SKB_SK_BUF_TYPE: LazyLock<Type> = LazyLock::new(|| {
1013 let data_id = MemoryId::new();
1014 assert!(offset_of!(__sk_buff, __bindgen_anon_2) == 168);
1015 ptr_to_struct_type(
1016 SK_BUF_ID.clone(),
1017 vec![
1018 scalar_range(0, offset_of!(__sk_buff, mark)),
1021 scalar_u32_mut_field(offset_of!(__sk_buff, mark)),
1022 scalar_range(offset_of!(__sk_buff, queue_mapping), offset_of!(__sk_buff, cb)),
1023 scalar_mut_range(offset_of!(__sk_buff, cb), offset_of!(__sk_buff, hash)),
1025 scalar_u32_field(offset_of!(__sk_buff, hash)),
1026 array_start_32_field(offset_of!(__sk_buff, data), data_id.clone()),
1027 array_end_32_field(offset_of!(__sk_buff, data_end), data_id),
1028 scalar_range(offset_of!(__sk_buff, napi_id), offset_of!(__sk_buff, data_meta)),
1029 scalar_u64_field(offset_of!(__sk_buff, tstamp)),
1030 scalar_u32_field(offset_of!(__sk_buff, gso_segs)),
1031 nullable_ptr_to_mem_field::<bpf_sock>(
1033 offset_of!(__sk_buff, __bindgen_anon_2),
1034 BPF_SOCK_ID.clone(),
1035 ),
1036 scalar_u32_field(offset_of!(__sk_buff, gso_size)),
1037 scalar_u64_field(offset_of!(__sk_buff, hwtstamp)),
1038 ],
1039 )
1040});
1041pub static CGROUP_SKB_ARGS: LazyLock<Vec<Type>> =
1042 LazyLock::new(|| vec![CGROUP_SKB_SK_BUF_TYPE.clone()]);
1043
1044static XDP_MD_ID: MemoryId = StructId::XdpMd.as_memory_id();
1045static XDP_MD_TYPE: LazyLock<Type> = LazyLock::new(|| {
1046 let data_id = MemoryId::new();
1047
1048 ptr_to_struct_type(
1049 XDP_MD_ID.clone(),
1050 vec![
1051 array_start_32_field(offset_of!(xdp_md, data), data_id.clone()),
1052 array_end_32_field(offset_of!(xdp_md, data_end), data_id),
1053 {
1055 let data_meta_offset = offset_of!(xdp_md, data_meta);
1056 scalar_field(data_meta_offset, std::mem::size_of::<xdp_md>() - data_meta_offset)
1057 },
1058 ],
1059 )
1060});
1061static XDP_MD_ARGS: LazyLock<Vec<Type>> = LazyLock::new(|| vec![XDP_MD_TYPE.clone()]);
1062
1063pub static BPF_USER_PT_REGS_T_ID: MemoryId = StructId::BpfUserPtRegs.as_memory_id();
1064pub static BPF_USER_PT_REGS_T_ARGS: LazyLock<Vec<Type>> =
1065 LazyLock::new(|| vec![ptr_to_mem_type::<bpf_user_pt_regs_t>(BPF_USER_PT_REGS_T_ID.clone())]);
1066
1067pub static BPF_SOCK_ID: MemoryId = StructId::BpfSock.as_memory_id();
1068pub static BPF_SOCK_TYPE: LazyLock<Type> =
1069 LazyLock::new(|| ptr_to_mem_type::<bpf_sock>(BPF_SOCK_ID.clone()));
1070pub static BPF_SOCK_ARGS: LazyLock<Vec<Type>> = LazyLock::new(|| vec![BPF_SOCK_TYPE.clone()]);
1071
1072pub static BPF_SOCKOPT_ID: MemoryId = StructId::BpfSockOpt.as_memory_id();
1073pub static BPF_SOCKOPT_TYPE: LazyLock<Type> = LazyLock::new(|| {
1074 let optval_id = MemoryId::new();
1075 ptr_to_struct_type(
1076 BPF_SOCKOPT_ID.clone(),
1077 vec![
1078 ptr_to_mem_field::<bpf_sock>(
1080 offset_of!(bpf_sockopt, __bindgen_anon_1),
1081 BPF_SOCK_ID.clone(),
1082 ),
1083 array_start_field(offset_of!(bpf_sockopt, __bindgen_anon_2), optval_id.clone()),
1085 array_end_field(offset_of!(bpf_sockopt, __bindgen_anon_3), optval_id),
1087 scalar_u32_field(offset_of!(bpf_sockopt, level)),
1088 scalar_u32_mut_field(offset_of!(bpf_sockopt, optname)),
1089 scalar_u32_mut_field(offset_of!(bpf_sockopt, optlen)),
1090 scalar_u32_mut_field(offset_of!(bpf_sockopt, retval)),
1091 ],
1092 )
1093});
1094pub static BPF_SOCKOPT_ARGS: LazyLock<Vec<Type>> = LazyLock::new(|| vec![BPF_SOCKOPT_TYPE.clone()]);
1095
1096pub static BPF_SOCK_ADDR_ID: MemoryId = StructId::BpfSockAddr.as_memory_id();
1105pub static BPF_SOCK_ADDR_TYPE: LazyLock<Type> = LazyLock::new(|| {
1106 ptr_to_struct_type(
1107 BPF_SOCK_ADDR_ID.clone(),
1108 vec![
1109 scalar_u32_field(offset_of!(bpf_sock_addr, user_family)),
1110 scalar_u32_field(offset_of!(bpf_sock_addr, user_ip4)),
1111 scalar_field(offset_of!(bpf_sock_addr, user_ip6), 16),
1112 scalar_u32_field(offset_of!(bpf_sock_addr, user_port)),
1113 scalar_u32_field(offset_of!(bpf_sock_addr, family)),
1114 scalar_u32_field(offset_of!(bpf_sock_addr, type_)),
1115 scalar_u32_field(offset_of!(bpf_sock_addr, protocol)),
1116 scalar_u32_field(offset_of!(bpf_sock_addr, msg_src_ip4)),
1117 scalar_field(offset_of!(bpf_sock_addr, msg_src_ip6), 16),
1118 ptr_to_mem_field::<bpf_sock>(
1120 offset_of!(bpf_sock_addr, __bindgen_anon_1),
1121 BPF_SOCK_ID.clone(),
1122 ),
1123 ],
1124 )
1125});
1126
1127pub static BPF_SOCK_ADDR_INET4_TYPE: LazyLock<Type> = LazyLock::new(|| {
1128 ptr_to_struct_type(
1129 BPF_SOCK_ADDR_ID.clone(),
1130 vec![
1131 scalar_u32_field(offset_of!(bpf_sock_addr, user_family)),
1132 scalar_u32_field(offset_of!(bpf_sock_addr, user_ip4)),
1133 scalar_u32_field(offset_of!(bpf_sock_addr, user_port)),
1134 scalar_u32_field(offset_of!(bpf_sock_addr, family)),
1135 scalar_u32_field(offset_of!(bpf_sock_addr, type_)),
1136 scalar_u32_field(offset_of!(bpf_sock_addr, protocol)),
1137 ptr_to_mem_field::<bpf_sock>(
1139 offset_of!(bpf_sock_addr, __bindgen_anon_1),
1140 BPF_SOCK_ID.clone(),
1141 ),
1142 ],
1143 )
1144});
1145pub static BPF_SOCK_ADDR_INET4_ARGS: LazyLock<Vec<Type>> =
1146 LazyLock::new(|| vec![BPF_SOCK_ADDR_INET4_TYPE.clone()]);
1147
1148pub static BPF_SOCK_ADDR_INET6_TYPE: LazyLock<Type> = LazyLock::new(|| {
1149 ptr_to_struct_type(
1150 BPF_SOCK_ADDR_ID.clone(),
1151 vec![
1152 scalar_u32_field(offset_of!(bpf_sock_addr, user_family)),
1153 scalar_field(offset_of!(bpf_sock_addr, user_ip6), 16),
1154 scalar_u32_field(offset_of!(bpf_sock_addr, user_port)),
1155 scalar_u32_field(offset_of!(bpf_sock_addr, family)),
1156 scalar_u32_field(offset_of!(bpf_sock_addr, type_)),
1157 scalar_u32_field(offset_of!(bpf_sock_addr, protocol)),
1158 ptr_to_mem_field::<bpf_sock>(
1160 offset_of!(bpf_sock_addr, __bindgen_anon_1),
1161 BPF_SOCK_ID.clone(),
1162 ),
1163 ],
1164 )
1165});
1166pub static BPF_SOCK_ADDR_INET6_ARGS: LazyLock<Vec<Type>> =
1167 LazyLock::new(|| vec![BPF_SOCK_ADDR_INET6_TYPE.clone()]);
1168
1169#[repr(C)]
1170#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1171struct TraceEntry {
1172 type_: u16,
1173 flags: u8,
1174 preemp_count: u8,
1175 pid: u32,
1176}
1177
1178#[repr(C)]
1179#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1180struct TraceEvent {
1181 trace_entry: TraceEntry,
1182 id: u64,
1183 args: [u64; 16],
1187}
1188
1189#[repr(C)]
1190#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
1191struct RawTraceEvent {
1192 args: [u64; 2],
1196}
1197
1198static BPF_TRACEPOINT_ID: LazyLock<MemoryId> = LazyLock::new(MemoryId::new);
1199static BPF_TRACEPOINT_ARGS: LazyLock<Vec<Type>> =
1200 LazyLock::new(|| vec![ptr_to_mem_type::<TraceEvent>(BPF_TRACEPOINT_ID.clone())]);
1201
1202static BPF_RAW_TRACEPOINT_ID: LazyLock<MemoryId> = LazyLock::new(MemoryId::new);
1203static BPF_RAW_TRACEPOINT_ARGS: LazyLock<Vec<Type>> =
1204 LazyLock::new(|| vec![ptr_to_mem_type::<RawTraceEvent>(BPF_RAW_TRACEPOINT_ID.clone())]);
1205
1206#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1208pub enum ProgramType {
1209 CgroupDevice,
1210 CgroupSkb,
1211 CgroupSock,
1212 CgroupSockAddr,
1213 CgroupSockopt,
1214 CgroupSysctl,
1215 Ext,
1216 FlowDissector,
1217 Kprobe,
1218 LircMode2,
1219 Lsm,
1220 LwtIn,
1221 LwtOut,
1222 LwtSeg6Local,
1223 LwtXmit,
1224 Netfilter,
1225 PerfEvent,
1226 RawTracepoint,
1227 RawTracepointWritable,
1228 SchedAct,
1229 SchedCls,
1230 SkLookup,
1231 SkMsg,
1232 SkReuseport,
1233 SkSkb,
1234 SocketFilter,
1235 SockOps,
1236 StructOps,
1237 Syscall,
1238 Tracepoint,
1239 Tracing,
1240 Unspec,
1241 Xdp,
1242}
1243
1244#[derive(thiserror::Error, Debug, PartialEq, Eq)]
1245pub enum EbpfApiError {
1246 #[error("Invalid program type: 0x{0:x}")]
1247 InvalidProgramType(u32),
1248
1249 #[error("Unsupported program type: {0:?}")]
1250 UnsupportedProgramType(ProgramType),
1251
1252 #[error("Invalid expected_attach_type: 0x{0:?}")]
1253 InvalidExpectedAttachType(AttachType),
1254}
1255
1256impl TryFrom<u32> for ProgramType {
1257 type Error = EbpfApiError;
1258
1259 fn try_from(program_type: u32) -> Result<Self, Self::Error> {
1260 match program_type {
1261 #![allow(non_upper_case_globals)]
1262 bpf_prog_type_BPF_PROG_TYPE_CGROUP_DEVICE => Ok(Self::CgroupDevice),
1263 bpf_prog_type_BPF_PROG_TYPE_CGROUP_SKB => Ok(Self::CgroupSkb),
1264 bpf_prog_type_BPF_PROG_TYPE_CGROUP_SOCK => Ok(Self::CgroupSock),
1265 bpf_prog_type_BPF_PROG_TYPE_CGROUP_SOCK_ADDR => Ok(Self::CgroupSockAddr),
1266 bpf_prog_type_BPF_PROG_TYPE_CGROUP_SOCKOPT => Ok(Self::CgroupSockopt),
1267 bpf_prog_type_BPF_PROG_TYPE_CGROUP_SYSCTL => Ok(Self::CgroupSysctl),
1268 bpf_prog_type_BPF_PROG_TYPE_EXT => Ok(Self::Ext),
1269 bpf_prog_type_BPF_PROG_TYPE_FLOW_DISSECTOR => Ok(Self::FlowDissector),
1270 bpf_prog_type_BPF_PROG_TYPE_KPROBE => Ok(Self::Kprobe),
1271 bpf_prog_type_BPF_PROG_TYPE_LIRC_MODE2 => Ok(Self::LircMode2),
1272 bpf_prog_type_BPF_PROG_TYPE_LSM => Ok(Self::Lsm),
1273 bpf_prog_type_BPF_PROG_TYPE_LWT_IN => Ok(Self::LwtIn),
1274 bpf_prog_type_BPF_PROG_TYPE_LWT_OUT => Ok(Self::LwtOut),
1275 bpf_prog_type_BPF_PROG_TYPE_LWT_SEG6LOCAL => Ok(Self::LwtSeg6Local),
1276 bpf_prog_type_BPF_PROG_TYPE_LWT_XMIT => Ok(Self::LwtXmit),
1277 bpf_prog_type_BPF_PROG_TYPE_NETFILTER => Ok(Self::Netfilter),
1278 bpf_prog_type_BPF_PROG_TYPE_PERF_EVENT => Ok(Self::PerfEvent),
1279 bpf_prog_type_BPF_PROG_TYPE_RAW_TRACEPOINT => Ok(Self::RawTracepoint),
1280 bpf_prog_type_BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE => Ok(Self::RawTracepointWritable),
1281 bpf_prog_type_BPF_PROG_TYPE_SCHED_ACT => Ok(Self::SchedAct),
1282 bpf_prog_type_BPF_PROG_TYPE_SCHED_CLS => Ok(Self::SchedCls),
1283 bpf_prog_type_BPF_PROG_TYPE_SK_LOOKUP => Ok(Self::SkLookup),
1284 bpf_prog_type_BPF_PROG_TYPE_SK_MSG => Ok(Self::SkMsg),
1285 bpf_prog_type_BPF_PROG_TYPE_SK_REUSEPORT => Ok(Self::SkReuseport),
1286 bpf_prog_type_BPF_PROG_TYPE_SK_SKB => Ok(Self::SkSkb),
1287 bpf_prog_type_BPF_PROG_TYPE_SOCK_OPS => Ok(Self::SockOps),
1288 bpf_prog_type_BPF_PROG_TYPE_SOCKET_FILTER => Ok(Self::SocketFilter),
1289 bpf_prog_type_BPF_PROG_TYPE_STRUCT_OPS => Ok(Self::StructOps),
1290 bpf_prog_type_BPF_PROG_TYPE_SYSCALL => Ok(Self::Syscall),
1291 bpf_prog_type_BPF_PROG_TYPE_TRACEPOINT => Ok(Self::Tracepoint),
1292 bpf_prog_type_BPF_PROG_TYPE_TRACING => Ok(Self::Tracing),
1293 bpf_prog_type_BPF_PROG_TYPE_UNSPEC => Ok(Self::Unspec),
1294 bpf_prog_type_BPF_PROG_TYPE_XDP => Ok(Self::Xdp),
1295 program_type @ _ => Err(EbpfApiError::InvalidProgramType(program_type)),
1296 }
1297 }
1298}
1299
1300impl From<ProgramType> for u32 {
1301 fn from(program_type: ProgramType) -> u32 {
1302 match program_type {
1303 ProgramType::CgroupDevice => bpf_prog_type_BPF_PROG_TYPE_CGROUP_DEVICE,
1304 ProgramType::CgroupSkb => bpf_prog_type_BPF_PROG_TYPE_CGROUP_SKB,
1305 ProgramType::CgroupSock => bpf_prog_type_BPF_PROG_TYPE_CGROUP_SOCK,
1306 ProgramType::CgroupSockAddr => bpf_prog_type_BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
1307 ProgramType::CgroupSockopt => bpf_prog_type_BPF_PROG_TYPE_CGROUP_SOCKOPT,
1308 ProgramType::CgroupSysctl => bpf_prog_type_BPF_PROG_TYPE_CGROUP_SYSCTL,
1309 ProgramType::Ext => bpf_prog_type_BPF_PROG_TYPE_EXT,
1310 ProgramType::FlowDissector => bpf_prog_type_BPF_PROG_TYPE_FLOW_DISSECTOR,
1311 ProgramType::Kprobe => bpf_prog_type_BPF_PROG_TYPE_KPROBE,
1312 ProgramType::LircMode2 => bpf_prog_type_BPF_PROG_TYPE_LIRC_MODE2,
1313 ProgramType::Lsm => bpf_prog_type_BPF_PROG_TYPE_LSM,
1314 ProgramType::LwtIn => bpf_prog_type_BPF_PROG_TYPE_LWT_IN,
1315 ProgramType::LwtOut => bpf_prog_type_BPF_PROG_TYPE_LWT_OUT,
1316 ProgramType::LwtSeg6Local => bpf_prog_type_BPF_PROG_TYPE_LWT_SEG6LOCAL,
1317 ProgramType::LwtXmit => bpf_prog_type_BPF_PROG_TYPE_LWT_XMIT,
1318 ProgramType::Netfilter => bpf_prog_type_BPF_PROG_TYPE_NETFILTER,
1319 ProgramType::PerfEvent => bpf_prog_type_BPF_PROG_TYPE_PERF_EVENT,
1320 ProgramType::RawTracepoint => bpf_prog_type_BPF_PROG_TYPE_RAW_TRACEPOINT,
1321 ProgramType::RawTracepointWritable => {
1322 bpf_prog_type_BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE
1323 }
1324 ProgramType::SchedAct => bpf_prog_type_BPF_PROG_TYPE_SCHED_ACT,
1325 ProgramType::SchedCls => bpf_prog_type_BPF_PROG_TYPE_SCHED_CLS,
1326 ProgramType::SkLookup => bpf_prog_type_BPF_PROG_TYPE_SK_LOOKUP,
1327 ProgramType::SkMsg => bpf_prog_type_BPF_PROG_TYPE_SK_MSG,
1328 ProgramType::SkReuseport => bpf_prog_type_BPF_PROG_TYPE_SK_REUSEPORT,
1329 ProgramType::SkSkb => bpf_prog_type_BPF_PROG_TYPE_SK_SKB,
1330 ProgramType::SockOps => bpf_prog_type_BPF_PROG_TYPE_SOCK_OPS,
1331 ProgramType::SocketFilter => bpf_prog_type_BPF_PROG_TYPE_SOCKET_FILTER,
1332 ProgramType::StructOps => bpf_prog_type_BPF_PROG_TYPE_STRUCT_OPS,
1333 ProgramType::Syscall => bpf_prog_type_BPF_PROG_TYPE_SYSCALL,
1334 ProgramType::Tracepoint => bpf_prog_type_BPF_PROG_TYPE_TRACEPOINT,
1335 ProgramType::Tracing => bpf_prog_type_BPF_PROG_TYPE_TRACING,
1336 ProgramType::Unspec => bpf_prog_type_BPF_PROG_TYPE_UNSPEC,
1337 ProgramType::Xdp => bpf_prog_type_BPF_PROG_TYPE_XDP,
1338 }
1339 }
1340}
1341
1342impl ProgramType {
1343 pub fn get_helpers(self) -> HashMap<u32, &'static HelperDefinition> {
1344 BPF_HELPERS_DEFINITIONS
1345 .iter()
1346 .filter_map(|(filter, helper)| filter.accept(self).then_some((helper.index, helper)))
1347 .collect()
1348 }
1349
1350 pub fn get_args(
1351 self,
1352 expected_attach_type: AttachType,
1353 ) -> Result<&'static [Type], EbpfApiError> {
1354 let args = match self {
1355 Self::SocketFilter => &SOCKET_FILTER_ARGS,
1356 Self::SchedAct | Self::SchedCls => &SCHED_ARGS,
1357 Self::CgroupSkb => match expected_attach_type {
1358 AttachType::Unspecified
1359 | AttachType::CgroupInetIngress
1360 | AttachType::CgroupInetEgress => &CGROUP_SKB_ARGS,
1361 _ => return Err(EbpfApiError::InvalidExpectedAttachType(expected_attach_type)),
1362 },
1363
1364 Self::Xdp => &XDP_MD_ARGS,
1365 Self::Kprobe => &BPF_USER_PT_REGS_T_ARGS,
1366 Self::Tracepoint => &BPF_TRACEPOINT_ARGS,
1367 Self::RawTracepoint => &BPF_RAW_TRACEPOINT_ARGS,
1368
1369 Self::CgroupSock => match expected_attach_type {
1370 AttachType::Unspecified
1371 | AttachType::CgroupInetIngress
1372 | AttachType::CgroupInetSockCreate
1373 | AttachType::CgroupInet4PostBind
1374 | AttachType::CgroupInet6PostBind
1375 | AttachType::CgroupInetSockRelease => &BPF_SOCK_ARGS,
1376 _ => return Err(EbpfApiError::InvalidExpectedAttachType(expected_attach_type)),
1377 },
1378
1379 Self::CgroupSockopt => match expected_attach_type {
1380 AttachType::CgroupGetsockopt | AttachType::CgroupSetsockopt => &BPF_SOCKOPT_ARGS,
1381 _ => return Err(EbpfApiError::InvalidExpectedAttachType(expected_attach_type)),
1382 },
1383
1384 Self::CgroupSockAddr => match expected_attach_type {
1385 AttachType::CgroupInet4Bind
1386 | AttachType::CgroupInet4Connect
1387 | AttachType::CgroupUdp4Sendmsg
1388 | AttachType::CgroupUdp4Recvmsg
1389 | AttachType::CgroupInet4Getpeername
1390 | AttachType::CgroupInet4Getsockname => &BPF_SOCK_ADDR_INET4_ARGS,
1391
1392 AttachType::CgroupInet6Bind
1393 | AttachType::CgroupInet6Connect
1394 | AttachType::CgroupUdp6Sendmsg
1395 | AttachType::CgroupUdp6Recvmsg
1396 | AttachType::CgroupInet6Getpeername
1397 | AttachType::CgroupInet6Getsockname => &BPF_SOCK_ADDR_INET6_ARGS,
1398
1399 _ => return Err(EbpfApiError::InvalidExpectedAttachType(expected_attach_type)),
1400 },
1401
1402 Self::CgroupDevice
1403 | Self::CgroupSysctl
1404 | Self::Ext
1405 | Self::FlowDissector
1406 | Self::LircMode2
1407 | Self::Lsm
1408 | Self::LwtIn
1409 | Self::LwtOut
1410 | Self::LwtSeg6Local
1411 | Self::LwtXmit
1412 | Self::Netfilter
1413 | Self::PerfEvent
1414 | Self::RawTracepointWritable
1415 | Self::SkLookup
1416 | Self::SkMsg
1417 | Self::SkReuseport
1418 | Self::SkSkb
1419 | Self::SockOps
1420 | Self::StructOps
1421 | Self::Syscall
1422 | Self::Tracing
1423 | Self::Unspec => return Err(EbpfApiError::UnsupportedProgramType(self)),
1424 };
1425 Ok(args)
1426 }
1427
1428 pub fn create_calling_context(
1429 self,
1430 expected_attach_type: AttachType,
1431 maps: Vec<MapSchema>,
1432 ) -> Result<CallingContext, EbpfApiError> {
1433 let args = self.get_args(expected_attach_type)?.to_vec();
1434 let packet_type = match self {
1435 Self::SocketFilter => Some(SOCKET_FILTER_SK_BUF_TYPE.clone()),
1436 Self::SchedAct | Self::SchedCls => Some(SCHED_ARG_TYPE.clone()),
1437 _ => None,
1438 };
1439 Ok(CallingContext { maps, helpers: self.get_helpers(), args, packet_type })
1440 }
1441}
1442
1443#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1444pub enum AttachType {
1445 CgroupInetIngress,
1446 CgroupInetEgress,
1447 CgroupInetSockCreate,
1448 CgroupSockOps,
1449 SkSkbStreamParser,
1450 SkSkbStreamVerdict,
1451 CgroupDevice,
1452 SkMsgVerdict,
1453 CgroupInet4Bind,
1454 CgroupInet6Bind,
1455 CgroupInet4Connect,
1456 CgroupInet6Connect,
1457 CgroupInet4PostBind,
1458 CgroupInet6PostBind,
1459 CgroupUdp4Sendmsg,
1460 CgroupUdp6Sendmsg,
1461 LircMode2,
1462 FlowDissector,
1463 CgroupSysctl,
1464 CgroupUdp4Recvmsg,
1465 CgroupUdp6Recvmsg,
1466 CgroupGetsockopt,
1467 CgroupSetsockopt,
1468 TraceRawTp,
1469 TraceFentry,
1470 TraceFexit,
1471 ModifyReturn,
1472 LsmMac,
1473 TraceIter,
1474 CgroupInet4Getpeername,
1475 CgroupInet6Getpeername,
1476 CgroupInet4Getsockname,
1477 CgroupInet6Getsockname,
1478 XdpDevmap,
1479 CgroupInetSockRelease,
1480 XdpCpumap,
1481 SkLookup,
1482 Xdp,
1483 SkSkbVerdict,
1484 SkReuseportSelect,
1485 SkReuseportSelectOrMigrate,
1486 PerfEvent,
1487 TraceKprobeMulti,
1488 LsmCgroup,
1489 StructOps,
1490 Netfilter,
1491 TcxIngress,
1492 TcxEgress,
1493 TraceUprobeMulti,
1494 CgroupUnixConnect,
1495 CgroupUnixSendmsg,
1496 CgroupUnixRecvmsg,
1497 CgroupUnixGetpeername,
1498 CgroupUnixGetsockname,
1499 NetkitPrimary,
1500 NetkitPeer,
1501 TraceKprobeSession,
1502
1503 Unspecified,
1506
1507 Invalid(u32),
1510}
1511
1512impl From<u32> for AttachType {
1513 fn from(attach_type: u32) -> Self {
1514 match attach_type {
1515 #![allow(non_upper_case_globals)]
1516 bpf_attach_type_BPF_CGROUP_INET_INGRESS => Self::CgroupInetIngress,
1517 bpf_attach_type_BPF_CGROUP_INET_EGRESS => Self::CgroupInetEgress,
1518 bpf_attach_type_BPF_CGROUP_INET_SOCK_CREATE => Self::CgroupInetSockCreate,
1519 bpf_attach_type_BPF_CGROUP_SOCK_OPS => Self::CgroupSockOps,
1520 bpf_attach_type_BPF_SK_SKB_STREAM_PARSER => Self::SkSkbStreamParser,
1521 bpf_attach_type_BPF_SK_SKB_STREAM_VERDICT => Self::SkSkbStreamVerdict,
1522 bpf_attach_type_BPF_CGROUP_DEVICE => Self::CgroupDevice,
1523 bpf_attach_type_BPF_SK_MSG_VERDICT => Self::SkMsgVerdict,
1524 bpf_attach_type_BPF_CGROUP_INET4_BIND => Self::CgroupInet4Bind,
1525 bpf_attach_type_BPF_CGROUP_INET6_BIND => Self::CgroupInet6Bind,
1526 bpf_attach_type_BPF_CGROUP_INET4_CONNECT => Self::CgroupInet4Connect,
1527 bpf_attach_type_BPF_CGROUP_INET6_CONNECT => Self::CgroupInet6Connect,
1528 bpf_attach_type_BPF_CGROUP_INET4_POST_BIND => Self::CgroupInet4PostBind,
1529 bpf_attach_type_BPF_CGROUP_INET6_POST_BIND => Self::CgroupInet6PostBind,
1530 bpf_attach_type_BPF_CGROUP_UDP4_SENDMSG => Self::CgroupUdp4Sendmsg,
1531 bpf_attach_type_BPF_CGROUP_UDP6_SENDMSG => Self::CgroupUdp6Sendmsg,
1532 bpf_attach_type_BPF_LIRC_MODE2 => Self::LircMode2,
1533 bpf_attach_type_BPF_FLOW_DISSECTOR => Self::FlowDissector,
1534 bpf_attach_type_BPF_CGROUP_SYSCTL => Self::CgroupSysctl,
1535 bpf_attach_type_BPF_CGROUP_UDP4_RECVMSG => Self::CgroupUdp4Recvmsg,
1536 bpf_attach_type_BPF_CGROUP_UDP6_RECVMSG => Self::CgroupUdp6Recvmsg,
1537 bpf_attach_type_BPF_CGROUP_GETSOCKOPT => Self::CgroupGetsockopt,
1538 bpf_attach_type_BPF_CGROUP_SETSOCKOPT => Self::CgroupSetsockopt,
1539 bpf_attach_type_BPF_TRACE_RAW_TP => Self::TraceRawTp,
1540 bpf_attach_type_BPF_TRACE_FENTRY => Self::TraceFentry,
1541 bpf_attach_type_BPF_TRACE_FEXIT => Self::TraceFexit,
1542 bpf_attach_type_BPF_MODIFY_RETURN => Self::ModifyReturn,
1543 bpf_attach_type_BPF_LSM_MAC => Self::LsmMac,
1544 bpf_attach_type_BPF_TRACE_ITER => Self::TraceIter,
1545 bpf_attach_type_BPF_CGROUP_INET4_GETPEERNAME => Self::CgroupInet4Getpeername,
1546 bpf_attach_type_BPF_CGROUP_INET6_GETPEERNAME => Self::CgroupInet6Getpeername,
1547 bpf_attach_type_BPF_CGROUP_INET4_GETSOCKNAME => Self::CgroupInet4Getsockname,
1548 bpf_attach_type_BPF_CGROUP_INET6_GETSOCKNAME => Self::CgroupInet6Getsockname,
1549 bpf_attach_type_BPF_XDP_DEVMAP => Self::XdpDevmap,
1550 bpf_attach_type_BPF_CGROUP_INET_SOCK_RELEASE => Self::CgroupInetSockRelease,
1551 bpf_attach_type_BPF_XDP_CPUMAP => Self::XdpCpumap,
1552 bpf_attach_type_BPF_SK_LOOKUP => Self::SkLookup,
1553 bpf_attach_type_BPF_XDP => Self::Xdp,
1554 bpf_attach_type_BPF_SK_SKB_VERDICT => Self::SkSkbVerdict,
1555 bpf_attach_type_BPF_SK_REUSEPORT_SELECT => Self::SkReuseportSelect,
1556 bpf_attach_type_BPF_SK_REUSEPORT_SELECT_OR_MIGRATE => Self::SkReuseportSelectOrMigrate,
1557 bpf_attach_type_BPF_PERF_EVENT => Self::PerfEvent,
1558 bpf_attach_type_BPF_TRACE_KPROBE_MULTI => Self::TraceKprobeMulti,
1559 bpf_attach_type_BPF_LSM_CGROUP => Self::LsmCgroup,
1560 bpf_attach_type_BPF_STRUCT_OPS => Self::StructOps,
1561 bpf_attach_type_BPF_NETFILTER => Self::Netfilter,
1562 bpf_attach_type_BPF_TCX_INGRESS => Self::TcxIngress,
1563 bpf_attach_type_BPF_TCX_EGRESS => Self::TcxEgress,
1564 bpf_attach_type_BPF_TRACE_UPROBE_MULTI => Self::TraceUprobeMulti,
1565 bpf_attach_type_BPF_CGROUP_UNIX_CONNECT => Self::CgroupUnixConnect,
1566 bpf_attach_type_BPF_CGROUP_UNIX_SENDMSG => Self::CgroupUnixSendmsg,
1567 bpf_attach_type_BPF_CGROUP_UNIX_RECVMSG => Self::CgroupUnixRecvmsg,
1568 bpf_attach_type_BPF_CGROUP_UNIX_GETPEERNAME => Self::CgroupUnixGetpeername,
1569 bpf_attach_type_BPF_CGROUP_UNIX_GETSOCKNAME => Self::CgroupUnixGetsockname,
1570 bpf_attach_type_BPF_NETKIT_PRIMARY => Self::NetkitPrimary,
1571 bpf_attach_type_BPF_NETKIT_PEER => Self::NetkitPeer,
1572 bpf_attach_type_BPF_TRACE_KPROBE_SESSION => Self::TraceKprobeSession,
1573
1574 u32::MAX => Self::Unspecified,
1575 _ => Self::Invalid(attach_type),
1576 }
1577 }
1578}
1579
1580impl From<AttachType> for u32 {
1581 fn from(attach_type: AttachType) -> Self {
1582 match attach_type {
1583 AttachType::CgroupInetIngress => bpf_attach_type_BPF_CGROUP_INET_INGRESS,
1584 AttachType::CgroupInetEgress => bpf_attach_type_BPF_CGROUP_INET_EGRESS,
1585 AttachType::CgroupInetSockCreate => bpf_attach_type_BPF_CGROUP_INET_SOCK_CREATE,
1586 AttachType::CgroupSockOps => bpf_attach_type_BPF_CGROUP_SOCK_OPS,
1587 AttachType::SkSkbStreamParser => bpf_attach_type_BPF_SK_SKB_STREAM_PARSER,
1588 AttachType::SkSkbStreamVerdict => bpf_attach_type_BPF_SK_SKB_STREAM_VERDICT,
1589 AttachType::CgroupDevice => bpf_attach_type_BPF_CGROUP_DEVICE,
1590 AttachType::SkMsgVerdict => bpf_attach_type_BPF_SK_MSG_VERDICT,
1591 AttachType::CgroupInet4Bind => bpf_attach_type_BPF_CGROUP_INET4_BIND,
1592 AttachType::CgroupInet6Bind => bpf_attach_type_BPF_CGROUP_INET6_BIND,
1593 AttachType::CgroupInet4Connect => bpf_attach_type_BPF_CGROUP_INET4_CONNECT,
1594 AttachType::CgroupInet6Connect => bpf_attach_type_BPF_CGROUP_INET6_CONNECT,
1595 AttachType::CgroupInet4PostBind => bpf_attach_type_BPF_CGROUP_INET4_POST_BIND,
1596 AttachType::CgroupInet6PostBind => bpf_attach_type_BPF_CGROUP_INET6_POST_BIND,
1597 AttachType::CgroupUdp4Sendmsg => bpf_attach_type_BPF_CGROUP_UDP4_SENDMSG,
1598 AttachType::CgroupUdp6Sendmsg => bpf_attach_type_BPF_CGROUP_UDP6_SENDMSG,
1599 AttachType::LircMode2 => bpf_attach_type_BPF_LIRC_MODE2,
1600 AttachType::FlowDissector => bpf_attach_type_BPF_FLOW_DISSECTOR,
1601 AttachType::CgroupSysctl => bpf_attach_type_BPF_CGROUP_SYSCTL,
1602 AttachType::CgroupUdp4Recvmsg => bpf_attach_type_BPF_CGROUP_UDP4_RECVMSG,
1603 AttachType::CgroupUdp6Recvmsg => bpf_attach_type_BPF_CGROUP_UDP6_RECVMSG,
1604 AttachType::CgroupGetsockopt => bpf_attach_type_BPF_CGROUP_GETSOCKOPT,
1605 AttachType::CgroupSetsockopt => bpf_attach_type_BPF_CGROUP_SETSOCKOPT,
1606 AttachType::TraceRawTp => bpf_attach_type_BPF_TRACE_RAW_TP,
1607 AttachType::TraceFentry => bpf_attach_type_BPF_TRACE_FENTRY,
1608 AttachType::TraceFexit => bpf_attach_type_BPF_TRACE_FEXIT,
1609 AttachType::ModifyReturn => bpf_attach_type_BPF_MODIFY_RETURN,
1610 AttachType::LsmMac => bpf_attach_type_BPF_LSM_MAC,
1611 AttachType::TraceIter => bpf_attach_type_BPF_TRACE_ITER,
1612 AttachType::CgroupInet4Getpeername => bpf_attach_type_BPF_CGROUP_INET4_GETPEERNAME,
1613 AttachType::CgroupInet6Getpeername => bpf_attach_type_BPF_CGROUP_INET6_GETPEERNAME,
1614 AttachType::CgroupInet4Getsockname => bpf_attach_type_BPF_CGROUP_INET4_GETSOCKNAME,
1615 AttachType::CgroupInet6Getsockname => bpf_attach_type_BPF_CGROUP_INET6_GETSOCKNAME,
1616 AttachType::XdpDevmap => bpf_attach_type_BPF_XDP_DEVMAP,
1617 AttachType::CgroupInetSockRelease => bpf_attach_type_BPF_CGROUP_INET_SOCK_RELEASE,
1618 AttachType::XdpCpumap => bpf_attach_type_BPF_XDP_CPUMAP,
1619 AttachType::SkLookup => bpf_attach_type_BPF_SK_LOOKUP,
1620 AttachType::Xdp => bpf_attach_type_BPF_XDP,
1621 AttachType::SkSkbVerdict => bpf_attach_type_BPF_SK_SKB_VERDICT,
1622 AttachType::SkReuseportSelect => bpf_attach_type_BPF_SK_REUSEPORT_SELECT,
1623 AttachType::SkReuseportSelectOrMigrate => {
1624 bpf_attach_type_BPF_SK_REUSEPORT_SELECT_OR_MIGRATE
1625 }
1626 AttachType::PerfEvent => bpf_attach_type_BPF_PERF_EVENT,
1627 AttachType::TraceKprobeMulti => bpf_attach_type_BPF_TRACE_KPROBE_MULTI,
1628 AttachType::LsmCgroup => bpf_attach_type_BPF_LSM_CGROUP,
1629 AttachType::StructOps => bpf_attach_type_BPF_STRUCT_OPS,
1630 AttachType::Netfilter => bpf_attach_type_BPF_NETFILTER,
1631 AttachType::TcxIngress => bpf_attach_type_BPF_TCX_INGRESS,
1632 AttachType::TcxEgress => bpf_attach_type_BPF_TCX_EGRESS,
1633 AttachType::TraceUprobeMulti => bpf_attach_type_BPF_TRACE_UPROBE_MULTI,
1634 AttachType::CgroupUnixConnect => bpf_attach_type_BPF_CGROUP_UNIX_CONNECT,
1635 AttachType::CgroupUnixSendmsg => bpf_attach_type_BPF_CGROUP_UNIX_SENDMSG,
1636 AttachType::CgroupUnixRecvmsg => bpf_attach_type_BPF_CGROUP_UNIX_RECVMSG,
1637 AttachType::CgroupUnixGetpeername => bpf_attach_type_BPF_CGROUP_UNIX_GETPEERNAME,
1638 AttachType::CgroupUnixGetsockname => bpf_attach_type_BPF_CGROUP_UNIX_GETSOCKNAME,
1639 AttachType::NetkitPrimary => bpf_attach_type_BPF_NETKIT_PRIMARY,
1640 AttachType::NetkitPeer => bpf_attach_type_BPF_NETKIT_PEER,
1641 AttachType::TraceKprobeSession => bpf_attach_type_BPF_TRACE_KPROBE_SESSION,
1642 AttachType::Unspecified => u32::MAX,
1643 AttachType::Invalid(attach_type) => attach_type,
1644 }
1645 }
1646}
1647
1648impl From<AttachType> for u64 {
1649 fn from(attach_type: AttachType) -> Self {
1650 (u32::from(attach_type)).into()
1651 }
1652}
1653
1654impl AttachType {
1655 pub fn is_cgroup(&self) -> bool {
1656 match self {
1657 Self::CgroupInetIngress
1658 | Self::CgroupInetEgress
1659 | Self::CgroupInetSockCreate
1660 | Self::CgroupSockOps
1661 | Self::CgroupDevice
1662 | Self::CgroupInet4Bind
1663 | Self::CgroupInet6Bind
1664 | Self::CgroupInet4Connect
1665 | Self::CgroupInet6Connect
1666 | Self::CgroupInet4PostBind
1667 | Self::CgroupInet6PostBind
1668 | Self::CgroupUdp4Sendmsg
1669 | Self::CgroupUdp6Sendmsg
1670 | Self::CgroupSysctl
1671 | Self::CgroupUdp4Recvmsg
1672 | Self::CgroupUdp6Recvmsg
1673 | Self::CgroupGetsockopt
1674 | Self::CgroupSetsockopt
1675 | Self::CgroupInet4Getpeername
1676 | Self::CgroupInet6Getpeername
1677 | Self::CgroupInet4Getsockname
1678 | Self::CgroupInet6Getsockname
1679 | Self::CgroupInetSockRelease
1680 | Self::CgroupUnixConnect
1681 | Self::CgroupUnixSendmsg
1682 | Self::CgroupUnixRecvmsg
1683 | Self::CgroupUnixGetpeername
1684 | Self::CgroupUnixGetsockname => true,
1685 _ => false,
1686 }
1687 }
1688
1689 pub fn get_program_type(&self) -> ProgramType {
1690 match self {
1691 Self::CgroupInetIngress | Self::CgroupInetEgress => ProgramType::CgroupSkb,
1692 Self::CgroupInetSockCreate
1693 | Self::CgroupInet4PostBind
1694 | Self::CgroupInet6PostBind
1695 | Self::CgroupInetSockRelease => ProgramType::CgroupSock,
1696 Self::CgroupSockOps | Self::CgroupGetsockopt | Self::CgroupSetsockopt => {
1697 ProgramType::CgroupSockopt
1698 }
1699 Self::CgroupDevice => ProgramType::CgroupDevice,
1700 Self::CgroupInet4Bind
1701 | Self::CgroupInet6Bind
1702 | Self::CgroupInet4Connect
1703 | Self::CgroupInet6Connect
1704 | Self::CgroupUdp4Sendmsg
1705 | Self::CgroupUdp6Sendmsg
1706 | Self::CgroupUdp4Recvmsg
1707 | Self::CgroupUdp6Recvmsg
1708 | Self::CgroupInet4Getpeername
1709 | Self::CgroupInet6Getpeername
1710 | Self::CgroupInet4Getsockname
1711 | Self::CgroupInet6Getsockname
1712 | Self::CgroupUnixConnect
1713 | Self::CgroupUnixSendmsg
1714 | Self::CgroupUnixRecvmsg
1715 | Self::CgroupUnixGetpeername
1716 | Self::CgroupUnixGetsockname => ProgramType::CgroupSockAddr,
1717 Self::CgroupSysctl => ProgramType::CgroupSysctl,
1718 Self::FlowDissector => ProgramType::FlowDissector,
1719 Self::LircMode2 => ProgramType::LircMode2,
1720 Self::LsmMac | Self::LsmCgroup => ProgramType::Lsm,
1721 Self::Netfilter => ProgramType::Netfilter,
1722 Self::PerfEvent => ProgramType::PerfEvent,
1723 Self::SkLookup => ProgramType::SkLookup,
1724 Self::SkMsgVerdict | Self::SkSkbVerdict => ProgramType::SkMsg,
1725 Self::SkReuseportSelect | Self::SkReuseportSelectOrMigrate => ProgramType::SkReuseport,
1726 Self::SkSkbStreamParser | Self::SkSkbStreamVerdict => ProgramType::SkSkb,
1727 Self::StructOps => ProgramType::StructOps,
1728 Self::TcxIngress | Self::TcxEgress | Self::NetkitPrimary | Self::NetkitPeer => {
1729 ProgramType::SchedCls
1730 }
1731 Self::TraceKprobeMulti | Self::TraceUprobeMulti | Self::TraceKprobeSession => {
1732 ProgramType::Kprobe
1733 }
1734 Self::TraceRawTp
1735 | Self::TraceFentry
1736 | Self::TraceFexit
1737 | Self::ModifyReturn
1738 | Self::TraceIter => ProgramType::Tracing,
1739 Self::XdpDevmap | Self::XdpCpumap | Self::Xdp => ProgramType::Xdp,
1740 Self::Unspecified | Self::Invalid(_) => ProgramType::Unspec,
1741 }
1742 }
1743
1744 pub fn is_compatible_with_expected_attach_type(self, expected: AttachType) -> bool {
1747 match self {
1749 Self::CgroupInetIngress | Self::CgroupInetEgress => matches!(
1752 expected,
1753 Self::Unspecified | Self::CgroupInetIngress | Self::CgroupInetEgress
1754 ),
1755
1756 Self::CgroupInetSockCreate | Self::CgroupSockOps => {
1759 self == expected || matches!(expected, Self::Unspecified | Self::CgroupInetIngress)
1760 }
1761
1762 Self::CgroupGetsockopt
1764 | Self::CgroupInet4Bind
1765 | Self::CgroupInet4Connect
1766 | Self::CgroupInet4Getpeername
1767 | Self::CgroupInet4Getsockname
1768 | Self::CgroupInet4PostBind
1769 | Self::CgroupInet6Bind
1770 | Self::CgroupInet6Connect
1771 | Self::CgroupInet6Getpeername
1772 | Self::CgroupInet6Getsockname
1773 | Self::CgroupInet6PostBind
1774 | Self::CgroupInetSockRelease
1775 | Self::CgroupSetsockopt
1776 | Self::CgroupUdp4Recvmsg
1777 | Self::CgroupUdp4Sendmsg
1778 | Self::CgroupUdp6Recvmsg
1779 | Self::CgroupUdp6Sendmsg
1780 | Self::CgroupUnixConnect
1781 | Self::CgroupUnixGetpeername
1782 | Self::CgroupUnixGetsockname
1783 | Self::CgroupUnixRecvmsg
1784 | Self::CgroupUnixSendmsg => self == expected,
1785
1786 _ => true,
1788 }
1789 }
1790}
1791
1792pub const SKF_AD_OFF: i32 = linux_uapi::SKF_AD_OFF;
1794pub const SKF_AD_PROTOCOL: i32 = linux_uapi::SKF_AD_PROTOCOL as i32;
1795pub const SKF_AD_PKTTYPE: i32 = linux_uapi::SKF_AD_PKTTYPE as i32;
1796pub const SKF_AD_IFINDEX: i32 = linux_uapi::SKF_AD_IFINDEX as i32;
1797pub const SKF_AD_NLATTR: i32 = linux_uapi::SKF_AD_NLATTR as i32;
1798pub const SKF_AD_NLATTR_NEST: i32 = linux_uapi::SKF_AD_NLATTR_NEST as i32;
1799pub const SKF_AD_MARK: i32 = linux_uapi::SKF_AD_MARK as i32;
1800pub const SKF_AD_QUEUE: i32 = linux_uapi::SKF_AD_QUEUE as i32;
1801pub const SKF_AD_HATYPE: i32 = linux_uapi::SKF_AD_HATYPE as i32;
1802pub const SKF_AD_RXHASH: i32 = linux_uapi::SKF_AD_RXHASH as i32;
1803pub const SKF_AD_CPU: i32 = linux_uapi::SKF_AD_CPU as i32;
1804pub const SKF_AD_ALU_XOR_X: i32 = linux_uapi::SKF_AD_ALU_XOR_X as i32;
1805pub const SKF_AD_VLAN_TAG: i32 = linux_uapi::SKF_AD_VLAN_TAG as i32;
1806pub const SKF_AD_VLAN_TAG_PRESENT: i32 = linux_uapi::SKF_AD_VLAN_TAG_PRESENT as i32;
1807pub const SKF_AD_PAY_OFFSET: i32 = linux_uapi::SKF_AD_PAY_OFFSET as i32;
1808pub const SKF_AD_RANDOM: i32 = linux_uapi::SKF_AD_RANDOM as i32;
1809pub const SKF_AD_VLAN_TPID: i32 = linux_uapi::SKF_AD_VLAN_TPID as i32;
1810pub const SKF_AD_MAX: i32 = linux_uapi::SKF_AD_MAX as i32;
1811
1812pub const SKF_NET_OFF: i32 = linux_uapi::SKF_NET_OFF;
1814
1815pub const SKF_LL_OFF: i32 = linux_uapi::SKF_LL_OFF;
1817
1818pub const SECCOMP_CBPF_CONFIG: CbpfConfig = CbpfConfig {
1819 len: CbpfLenInstruction::Static { len: size_of::<seccomp_data>() as i32 },
1820 allow_msh: false,
1821};
1822
1823pub const SOCKET_FILTER_CBPF_CONFIG: CbpfConfig = CbpfConfig {
1824 len: CbpfLenInstruction::ContextField { offset: offset_of!(__sk_buff, len) as i16 },
1825 allow_msh: true,
1826};
1827
1828#[cfg(test)]
1829mod tests {
1830 use super::*;
1831
1832 #[test]
1833 fn test_invalid_program_type() {
1834 assert_eq!(
1835 ProgramType::try_from(0x77777777),
1836 Err(EbpfApiError::InvalidProgramType(0x77777777))
1837 );
1838 assert_eq!(
1839 ProgramType::try_from(u32::MAX),
1840 Err(EbpfApiError::InvalidProgramType(u32::MAX))
1841 );
1842 }
1843
1844 #[test]
1845 fn test_invalid_struct_id() {
1846 assert_eq!(StructId::try_from(&MemoryId::from_raw(0)), Err(()));
1847 assert_eq!(StructId::try_from(&MemoryId::from_raw(7)), Err(()));
1848 assert_eq!(StructId::try_from(&MemoryId::from_raw(u64::MAX)), Err(()));
1849 }
1850}