1#![doc = "Binder interface over generic netlink\n"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12 consts,
13 traits::{NetlinkRequest, Protocol},
14 utils::*,
15};
16pub const PROTONAME: &str = "binder";
17pub const PROTONAME_CSTR: &CStr = c"binder";
18#[derive(Clone)]
19pub enum Report<'a> {
20 #[doc = "The enum binder_driver_return_protocol returned to the sender.\n"]
21 Error(u32),
22 #[doc = "The binder context where the transaction occurred.\n"]
23 Context(&'a CStr),
24 #[doc = "The PID of the sender process.\n"]
25 FromPid(u32),
26 #[doc = "The TID of the sender thread.\n"]
27 FromTid(u32),
28 #[doc = "The PID of the recipient process. This attribute may not be present if\nthe target could not be determined.\n"]
29 ToPid(u32),
30 #[doc = "The TID of the recipient thread. This attribute may not be present if\nthe target could not be determined.\n"]
31 ToTid(u32),
32 #[doc = "When present, indicates the failed transaction is a reply.\n"]
33 IsReply(()),
34 #[doc = "The bitmask of enum transaction_flags from the transaction.\n"]
35 Flags(u32),
36 #[doc = "The application-defined code from the transaction.\n"]
37 Code(u32),
38 #[doc = "The transaction payload size in bytes.\n"]
39 DataSize(u32),
40}
41impl<'a> IterableReport<'a> {
42 #[doc = "The enum binder_driver_return_protocol returned to the sender.\n"]
43 pub fn get_error(&self) -> Result<u32, ErrorContext> {
44 let mut iter = self.clone();
45 iter.pos = 0;
46 for attr in iter {
47 if let Ok(Report::Error(val)) = attr {
48 return Ok(val);
49 }
50 }
51 Err(ErrorContext::new_missing(
52 "Report",
53 "Error",
54 self.orig_loc,
55 self.buf.as_ptr() as usize,
56 ))
57 }
58 #[doc = "The binder context where the transaction occurred.\n"]
59 pub fn get_context(&self) -> Result<&'a CStr, ErrorContext> {
60 let mut iter = self.clone();
61 iter.pos = 0;
62 for attr in iter {
63 if let Ok(Report::Context(val)) = attr {
64 return Ok(val);
65 }
66 }
67 Err(ErrorContext::new_missing(
68 "Report",
69 "Context",
70 self.orig_loc,
71 self.buf.as_ptr() as usize,
72 ))
73 }
74 #[doc = "The PID of the sender process.\n"]
75 pub fn get_from_pid(&self) -> Result<u32, ErrorContext> {
76 let mut iter = self.clone();
77 iter.pos = 0;
78 for attr in iter {
79 if let Ok(Report::FromPid(val)) = attr {
80 return Ok(val);
81 }
82 }
83 Err(ErrorContext::new_missing(
84 "Report",
85 "FromPid",
86 self.orig_loc,
87 self.buf.as_ptr() as usize,
88 ))
89 }
90 #[doc = "The TID of the sender thread.\n"]
91 pub fn get_from_tid(&self) -> Result<u32, ErrorContext> {
92 let mut iter = self.clone();
93 iter.pos = 0;
94 for attr in iter {
95 if let Ok(Report::FromTid(val)) = attr {
96 return Ok(val);
97 }
98 }
99 Err(ErrorContext::new_missing(
100 "Report",
101 "FromTid",
102 self.orig_loc,
103 self.buf.as_ptr() as usize,
104 ))
105 }
106 #[doc = "The PID of the recipient process. This attribute may not be present if\nthe target could not be determined.\n"]
107 pub fn get_to_pid(&self) -> Result<u32, ErrorContext> {
108 let mut iter = self.clone();
109 iter.pos = 0;
110 for attr in iter {
111 if let Ok(Report::ToPid(val)) = attr {
112 return Ok(val);
113 }
114 }
115 Err(ErrorContext::new_missing(
116 "Report",
117 "ToPid",
118 self.orig_loc,
119 self.buf.as_ptr() as usize,
120 ))
121 }
122 #[doc = "The TID of the recipient thread. This attribute may not be present if\nthe target could not be determined.\n"]
123 pub fn get_to_tid(&self) -> Result<u32, ErrorContext> {
124 let mut iter = self.clone();
125 iter.pos = 0;
126 for attr in iter {
127 if let Ok(Report::ToTid(val)) = attr {
128 return Ok(val);
129 }
130 }
131 Err(ErrorContext::new_missing(
132 "Report",
133 "ToTid",
134 self.orig_loc,
135 self.buf.as_ptr() as usize,
136 ))
137 }
138 #[doc = "When present, indicates the failed transaction is a reply.\n"]
139 pub fn get_is_reply(&self) -> Result<(), ErrorContext> {
140 let mut iter = self.clone();
141 iter.pos = 0;
142 for attr in iter {
143 if let Ok(Report::IsReply(val)) = attr {
144 return Ok(val);
145 }
146 }
147 Err(ErrorContext::new_missing(
148 "Report",
149 "IsReply",
150 self.orig_loc,
151 self.buf.as_ptr() as usize,
152 ))
153 }
154 #[doc = "The bitmask of enum transaction_flags from the transaction.\n"]
155 pub fn get_flags(&self) -> Result<u32, ErrorContext> {
156 let mut iter = self.clone();
157 iter.pos = 0;
158 for attr in iter {
159 if let Ok(Report::Flags(val)) = attr {
160 return Ok(val);
161 }
162 }
163 Err(ErrorContext::new_missing(
164 "Report",
165 "Flags",
166 self.orig_loc,
167 self.buf.as_ptr() as usize,
168 ))
169 }
170 #[doc = "The application-defined code from the transaction.\n"]
171 pub fn get_code(&self) -> Result<u32, ErrorContext> {
172 let mut iter = self.clone();
173 iter.pos = 0;
174 for attr in iter {
175 if let Ok(Report::Code(val)) = attr {
176 return Ok(val);
177 }
178 }
179 Err(ErrorContext::new_missing(
180 "Report",
181 "Code",
182 self.orig_loc,
183 self.buf.as_ptr() as usize,
184 ))
185 }
186 #[doc = "The transaction payload size in bytes.\n"]
187 pub fn get_data_size(&self) -> Result<u32, ErrorContext> {
188 let mut iter = self.clone();
189 iter.pos = 0;
190 for attr in iter {
191 if let Ok(Report::DataSize(val)) = attr {
192 return Ok(val);
193 }
194 }
195 Err(ErrorContext::new_missing(
196 "Report",
197 "DataSize",
198 self.orig_loc,
199 self.buf.as_ptr() as usize,
200 ))
201 }
202}
203impl Report<'_> {
204 pub fn new<'a>(buf: &'a [u8]) -> IterableReport<'a> {
205 IterableReport::with_loc(buf, buf.as_ptr() as usize)
206 }
207 fn attr_from_type(r#type: u16) -> Option<&'static str> {
208 let res = match r#type {
209 1u16 => "Error",
210 2u16 => "Context",
211 3u16 => "FromPid",
212 4u16 => "FromTid",
213 5u16 => "ToPid",
214 6u16 => "ToTid",
215 7u16 => "IsReply",
216 8u16 => "Flags",
217 9u16 => "Code",
218 10u16 => "DataSize",
219 _ => return None,
220 };
221 Some(res)
222 }
223}
224#[derive(Clone, Copy, Default)]
225pub struct IterableReport<'a> {
226 buf: &'a [u8],
227 pos: usize,
228 orig_loc: usize,
229}
230impl<'a> IterableReport<'a> {
231 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
232 Self {
233 buf,
234 pos: 0,
235 orig_loc,
236 }
237 }
238 pub fn get_buf(&self) -> &'a [u8] {
239 self.buf
240 }
241}
242impl<'a> Iterator for IterableReport<'a> {
243 type Item = Result<Report<'a>, ErrorContext>;
244 fn next(&mut self) -> Option<Self::Item> {
245 let mut pos;
246 let mut r#type;
247 loop {
248 pos = self.pos;
249 r#type = None;
250 if self.buf.len() == self.pos {
251 return None;
252 }
253 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
254 self.pos = self.buf.len();
255 break;
256 };
257 r#type = Some(header.r#type);
258 let res = match header.r#type {
259 1u16 => Report::Error({
260 let res = parse_u32(next);
261 let Some(val) = res else { break };
262 val
263 }),
264 2u16 => Report::Context({
265 let res = CStr::from_bytes_with_nul(next).ok();
266 let Some(val) = res else { break };
267 val
268 }),
269 3u16 => Report::FromPid({
270 let res = parse_u32(next);
271 let Some(val) = res else { break };
272 val
273 }),
274 4u16 => Report::FromTid({
275 let res = parse_u32(next);
276 let Some(val) = res else { break };
277 val
278 }),
279 5u16 => Report::ToPid({
280 let res = parse_u32(next);
281 let Some(val) = res else { break };
282 val
283 }),
284 6u16 => Report::ToTid({
285 let res = parse_u32(next);
286 let Some(val) = res else { break };
287 val
288 }),
289 7u16 => Report::IsReply(()),
290 8u16 => Report::Flags({
291 let res = parse_u32(next);
292 let Some(val) = res else { break };
293 val
294 }),
295 9u16 => Report::Code({
296 let res = parse_u32(next);
297 let Some(val) = res else { break };
298 val
299 }),
300 10u16 => Report::DataSize({
301 let res = parse_u32(next);
302 let Some(val) = res else { break };
303 val
304 }),
305 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
306 n => continue,
307 };
308 return Some(Ok(res));
309 }
310 Some(Err(ErrorContext::new(
311 "Report",
312 r#type.and_then(|t| Report::attr_from_type(t)),
313 self.orig_loc,
314 self.buf.as_ptr().wrapping_add(pos) as usize,
315 )))
316 }
317}
318impl<'a> std::fmt::Debug for IterableReport<'_> {
319 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
320 let mut fmt = f.debug_struct("Report");
321 for attr in self.clone() {
322 let attr = match attr {
323 Ok(a) => a,
324 Err(err) => {
325 fmt.finish()?;
326 f.write_str("Err(")?;
327 err.fmt(f)?;
328 return f.write_str(")");
329 }
330 };
331 match attr {
332 Report::Error(val) => fmt.field("Error", &val),
333 Report::Context(val) => fmt.field("Context", &val),
334 Report::FromPid(val) => fmt.field("FromPid", &val),
335 Report::FromTid(val) => fmt.field("FromTid", &val),
336 Report::ToPid(val) => fmt.field("ToPid", &val),
337 Report::ToTid(val) => fmt.field("ToTid", &val),
338 Report::IsReply(val) => fmt.field("IsReply", &val),
339 Report::Flags(val) => fmt.field("Flags", &val),
340 Report::Code(val) => fmt.field("Code", &val),
341 Report::DataSize(val) => fmt.field("DataSize", &val),
342 };
343 }
344 fmt.finish()
345 }
346}
347impl IterableReport<'_> {
348 pub fn lookup_attr(
349 &self,
350 offset: usize,
351 missing_type: Option<u16>,
352 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
353 let mut stack = Vec::new();
354 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
355 if missing_type.is_some() && cur == offset {
356 stack.push(("Report", offset));
357 return (stack, missing_type.and_then(|t| Report::attr_from_type(t)));
358 }
359 if cur > offset || cur + self.buf.len() < offset {
360 return (stack, None);
361 }
362 let mut attrs = self.clone();
363 let mut last_off = cur + attrs.pos;
364 while let Some(attr) = attrs.next() {
365 let Ok(attr) = attr else { break };
366 match attr {
367 Report::Error(val) => {
368 if last_off == offset {
369 stack.push(("Error", last_off));
370 break;
371 }
372 }
373 Report::Context(val) => {
374 if last_off == offset {
375 stack.push(("Context", last_off));
376 break;
377 }
378 }
379 Report::FromPid(val) => {
380 if last_off == offset {
381 stack.push(("FromPid", last_off));
382 break;
383 }
384 }
385 Report::FromTid(val) => {
386 if last_off == offset {
387 stack.push(("FromTid", last_off));
388 break;
389 }
390 }
391 Report::ToPid(val) => {
392 if last_off == offset {
393 stack.push(("ToPid", last_off));
394 break;
395 }
396 }
397 Report::ToTid(val) => {
398 if last_off == offset {
399 stack.push(("ToTid", last_off));
400 break;
401 }
402 }
403 Report::IsReply(val) => {
404 if last_off == offset {
405 stack.push(("IsReply", last_off));
406 break;
407 }
408 }
409 Report::Flags(val) => {
410 if last_off == offset {
411 stack.push(("Flags", last_off));
412 break;
413 }
414 }
415 Report::Code(val) => {
416 if last_off == offset {
417 stack.push(("Code", last_off));
418 break;
419 }
420 }
421 Report::DataSize(val) => {
422 if last_off == offset {
423 stack.push(("DataSize", last_off));
424 break;
425 }
426 }
427 _ => {}
428 };
429 last_off = cur + attrs.pos;
430 }
431 if !stack.is_empty() {
432 stack.push(("Report", cur));
433 }
434 (stack, None)
435 }
436}
437pub struct PushReport<Prev: Pusher> {
438 pub(crate) prev: Option<Prev>,
439 pub(crate) header_offset: Option<usize>,
440}
441impl<Prev: Pusher> Pusher for PushReport<Prev> {
442 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
443 self.prev.as_mut().unwrap().as_vec_mut()
444 }
445 fn as_vec(&self) -> &Vec<u8> {
446 self.prev.as_ref().unwrap().as_vec()
447 }
448}
449impl<Prev: Pusher> PushReport<Prev> {
450 pub fn new(prev: Prev) -> Self {
451 Self {
452 prev: Some(prev),
453 header_offset: None,
454 }
455 }
456 pub fn end_nested(mut self) -> Prev {
457 let mut prev = self.prev.take().unwrap();
458 if let Some(header_offset) = &self.header_offset {
459 finalize_nested_header(prev.as_vec_mut(), *header_offset);
460 }
461 prev
462 }
463 #[doc = "The enum binder_driver_return_protocol returned to the sender.\n"]
464 pub fn push_error(mut self, value: u32) -> Self {
465 push_header(self.as_vec_mut(), 1u16, 4 as u16);
466 self.as_vec_mut().extend(value.to_ne_bytes());
467 self
468 }
469 #[doc = "The binder context where the transaction occurred.\n"]
470 pub fn push_context(mut self, value: &CStr) -> Self {
471 push_header(
472 self.as_vec_mut(),
473 2u16,
474 value.to_bytes_with_nul().len() as u16,
475 );
476 self.as_vec_mut().extend(value.to_bytes_with_nul());
477 self
478 }
479 #[doc = "The binder context where the transaction occurred.\n"]
480 pub fn push_context_bytes(mut self, value: &[u8]) -> Self {
481 push_header(self.as_vec_mut(), 2u16, (value.len() + 1) as u16);
482 self.as_vec_mut().extend(value);
483 self.as_vec_mut().push(0);
484 self
485 }
486 #[doc = "The PID of the sender process.\n"]
487 pub fn push_from_pid(mut self, value: u32) -> Self {
488 push_header(self.as_vec_mut(), 3u16, 4 as u16);
489 self.as_vec_mut().extend(value.to_ne_bytes());
490 self
491 }
492 #[doc = "The TID of the sender thread.\n"]
493 pub fn push_from_tid(mut self, value: u32) -> Self {
494 push_header(self.as_vec_mut(), 4u16, 4 as u16);
495 self.as_vec_mut().extend(value.to_ne_bytes());
496 self
497 }
498 #[doc = "The PID of the recipient process. This attribute may not be present if\nthe target could not be determined.\n"]
499 pub fn push_to_pid(mut self, value: u32) -> Self {
500 push_header(self.as_vec_mut(), 5u16, 4 as u16);
501 self.as_vec_mut().extend(value.to_ne_bytes());
502 self
503 }
504 #[doc = "The TID of the recipient thread. This attribute may not be present if\nthe target could not be determined.\n"]
505 pub fn push_to_tid(mut self, value: u32) -> Self {
506 push_header(self.as_vec_mut(), 6u16, 4 as u16);
507 self.as_vec_mut().extend(value.to_ne_bytes());
508 self
509 }
510 #[doc = "When present, indicates the failed transaction is a reply.\n"]
511 pub fn push_is_reply(mut self, value: ()) -> Self {
512 push_header(self.as_vec_mut(), 7u16, 0 as u16);
513 self
514 }
515 #[doc = "The bitmask of enum transaction_flags from the transaction.\n"]
516 pub fn push_flags(mut self, value: u32) -> Self {
517 push_header(self.as_vec_mut(), 8u16, 4 as u16);
518 self.as_vec_mut().extend(value.to_ne_bytes());
519 self
520 }
521 #[doc = "The application-defined code from the transaction.\n"]
522 pub fn push_code(mut self, value: u32) -> Self {
523 push_header(self.as_vec_mut(), 9u16, 4 as u16);
524 self.as_vec_mut().extend(value.to_ne_bytes());
525 self
526 }
527 #[doc = "The transaction payload size in bytes.\n"]
528 pub fn push_data_size(mut self, value: u32) -> Self {
529 push_header(self.as_vec_mut(), 10u16, 4 as u16);
530 self.as_vec_mut().extend(value.to_ne_bytes());
531 self
532 }
533}
534impl<Prev: Pusher> Drop for PushReport<Prev> {
535 fn drop(&mut self) {
536 if let Some(prev) = &mut self.prev {
537 if let Some(header_offset) = &self.header_offset {
538 finalize_nested_header(prev.as_vec_mut(), *header_offset);
539 }
540 }
541 }
542}
543#[doc = "Notify attributes:\n- [`.get_error()`](IterableReport::get_error)\n- [`.get_context()`](IterableReport::get_context)\n- [`.get_from_pid()`](IterableReport::get_from_pid)\n- [`.get_from_tid()`](IterableReport::get_from_tid)\n- [`.get_to_pid()`](IterableReport::get_to_pid)\n- [`.get_to_tid()`](IterableReport::get_to_tid)\n- [`.get_is_reply()`](IterableReport::get_is_reply)\n- [`.get_flags()`](IterableReport::get_flags)\n- [`.get_code()`](IterableReport::get_code)\n- [`.get_data_size()`](IterableReport::get_data_size)\n"]
544#[derive(Debug)]
545pub struct OpReportNotif;
546impl OpReportNotif {
547 pub const CMD: u8 = 1u8;
548 pub fn decode_notif<'a>(buf: &'a [u8]) -> IterableReport<'a> {
549 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
550 IterableReport::with_loc(attrs, buf.as_ptr() as usize)
551 }
552}
553pub struct NotifGroup;
554impl NotifGroup {
555 #[doc = "Notifications:\n- [`OpReportNotif`]\n"]
556 pub const REPORT: &str = "report";
557 #[doc = "Notifications:\n- [`OpReportNotif`]\n"]
558 pub const REPORT_CSTR: &CStr = c"report";
559}
560#[cfg(test)]
561mod generated_tests {
562 use super::*;
563 #[test]
564 fn tests() {
565 let _ = IterableReport::get_code;
566 let _ = IterableReport::get_context;
567 let _ = IterableReport::get_data_size;
568 let _ = IterableReport::get_error;
569 let _ = IterableReport::get_flags;
570 let _ = IterableReport::get_from_pid;
571 let _ = IterableReport::get_from_tid;
572 let _ = IterableReport::get_is_reply;
573 let _ = IterableReport::get_to_pid;
574 let _ = IterableReport::get_to_tid;
575 let _ = OpReportNotif;
576 }
577}