1#![doc = "Binder interface over generic netlink"]
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\\."]
21 Error(u32),
22 #[doc = "The binder context where the transaction occurred\\."]
23 Context(&'a CStr),
24 #[doc = "The PID of the sender process\\."]
25 FromPid(u32),
26 #[doc = "The TID of the sender thread\\."]
27 FromTid(u32),
28 #[doc = "The PID of the recipient process\\. This attribute may not be present\nif the target could not be determined\\.\n"]
29 ToPid(u32),
30 #[doc = "The TID of the recipient thread\\. This attribute may not be present\nif the target could not be determined\\.\n"]
31 ToTid(u32),
32 #[doc = "When present, indicates the failed transaction is a reply\\."]
33 IsReply(()),
34 #[doc = "The bitmask of enum transaction\\_flags from the transaction\\."]
35 Flags(u32),
36 #[doc = "The application\\-defined code from the transaction\\."]
37 Code(u32),
38 #[doc = "The transaction payload size in bytes\\."]
39 DataSize(u32),
40}
41impl<'a> IterableReport<'a> {
42 #[doc = "The enum binder\\_driver\\_return\\_protocol returned to the sender\\."]
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 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\\."]
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 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\\."]
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 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\\."]
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 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\nif the 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 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\nif the 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 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\\."]
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 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\\."]
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 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\\."]
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 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\\."]
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 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 pos = self.pos;
246 let mut r#type;
247 loop {
248 r#type = None;
249 if self.buf.len() == self.pos {
250 return None;
251 }
252 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
253 break;
254 };
255 r#type = Some(header.r#type);
256 let res = match header.r#type {
257 1u16 => Report::Error({
258 let res = parse_u32(next);
259 let Some(val) = res else { break };
260 val
261 }),
262 2u16 => Report::Context({
263 let res = CStr::from_bytes_with_nul(next).ok();
264 let Some(val) = res else { break };
265 val
266 }),
267 3u16 => Report::FromPid({
268 let res = parse_u32(next);
269 let Some(val) = res else { break };
270 val
271 }),
272 4u16 => Report::FromTid({
273 let res = parse_u32(next);
274 let Some(val) = res else { break };
275 val
276 }),
277 5u16 => Report::ToPid({
278 let res = parse_u32(next);
279 let Some(val) = res else { break };
280 val
281 }),
282 6u16 => Report::ToTid({
283 let res = parse_u32(next);
284 let Some(val) = res else { break };
285 val
286 }),
287 7u16 => Report::IsReply(()),
288 8u16 => Report::Flags({
289 let res = parse_u32(next);
290 let Some(val) = res else { break };
291 val
292 }),
293 9u16 => Report::Code({
294 let res = parse_u32(next);
295 let Some(val) = res else { break };
296 val
297 }),
298 10u16 => Report::DataSize({
299 let res = parse_u32(next);
300 let Some(val) = res else { break };
301 val
302 }),
303 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
304 n => continue,
305 };
306 return Some(Ok(res));
307 }
308 Some(Err(ErrorContext::new(
309 "Report",
310 r#type.and_then(|t| Report::attr_from_type(t)),
311 self.orig_loc,
312 self.buf.as_ptr().wrapping_add(pos) as usize,
313 )))
314 }
315}
316impl<'a> std::fmt::Debug for IterableReport<'_> {
317 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
318 let mut fmt = f.debug_struct("Report");
319 for attr in self.clone() {
320 let attr = match attr {
321 Ok(a) => a,
322 Err(err) => {
323 fmt.finish()?;
324 f.write_str("Err(")?;
325 err.fmt(f)?;
326 return f.write_str(")");
327 }
328 };
329 match attr {
330 Report::Error(val) => fmt.field("Error", &val),
331 Report::Context(val) => fmt.field("Context", &val),
332 Report::FromPid(val) => fmt.field("FromPid", &val),
333 Report::FromTid(val) => fmt.field("FromTid", &val),
334 Report::ToPid(val) => fmt.field("ToPid", &val),
335 Report::ToTid(val) => fmt.field("ToTid", &val),
336 Report::IsReply(val) => fmt.field("IsReply", &val),
337 Report::Flags(val) => fmt.field("Flags", &val),
338 Report::Code(val) => fmt.field("Code", &val),
339 Report::DataSize(val) => fmt.field("DataSize", &val),
340 };
341 }
342 fmt.finish()
343 }
344}
345impl IterableReport<'_> {
346 pub fn lookup_attr(
347 &self,
348 offset: usize,
349 missing_type: Option<u16>,
350 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
351 let mut stack = Vec::new();
352 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
353 if missing_type.is_some() && cur == offset {
354 stack.push(("Report", offset));
355 return (stack, missing_type.and_then(|t| Report::attr_from_type(t)));
356 }
357 if cur > offset || cur + self.buf.len() < offset {
358 return (stack, None);
359 }
360 let mut attrs = self.clone();
361 let mut last_off = cur + attrs.pos;
362 while let Some(attr) = attrs.next() {
363 let Ok(attr) = attr else { break };
364 match attr {
365 Report::Error(val) => {
366 if last_off == offset {
367 stack.push(("Error", last_off));
368 break;
369 }
370 }
371 Report::Context(val) => {
372 if last_off == offset {
373 stack.push(("Context", last_off));
374 break;
375 }
376 }
377 Report::FromPid(val) => {
378 if last_off == offset {
379 stack.push(("FromPid", last_off));
380 break;
381 }
382 }
383 Report::FromTid(val) => {
384 if last_off == offset {
385 stack.push(("FromTid", last_off));
386 break;
387 }
388 }
389 Report::ToPid(val) => {
390 if last_off == offset {
391 stack.push(("ToPid", last_off));
392 break;
393 }
394 }
395 Report::ToTid(val) => {
396 if last_off == offset {
397 stack.push(("ToTid", last_off));
398 break;
399 }
400 }
401 Report::IsReply(val) => {
402 if last_off == offset {
403 stack.push(("IsReply", last_off));
404 break;
405 }
406 }
407 Report::Flags(val) => {
408 if last_off == offset {
409 stack.push(("Flags", last_off));
410 break;
411 }
412 }
413 Report::Code(val) => {
414 if last_off == offset {
415 stack.push(("Code", last_off));
416 break;
417 }
418 }
419 Report::DataSize(val) => {
420 if last_off == offset {
421 stack.push(("DataSize", last_off));
422 break;
423 }
424 }
425 _ => {}
426 };
427 last_off = cur + attrs.pos;
428 }
429 if !stack.is_empty() {
430 stack.push(("Report", cur));
431 }
432 (stack, None)
433 }
434}
435pub struct PushReport<Prev: Rec> {
436 pub(crate) prev: Option<Prev>,
437 pub(crate) header_offset: Option<usize>,
438}
439impl<Prev: Rec> Rec for PushReport<Prev> {
440 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
441 self.prev.as_mut().unwrap().as_rec_mut()
442 }
443 fn as_rec(&self) -> &Vec<u8> {
444 self.prev.as_ref().unwrap().as_rec()
445 }
446}
447impl<Prev: Rec> PushReport<Prev> {
448 pub fn new(prev: Prev) -> Self {
449 Self {
450 prev: Some(prev),
451 header_offset: None,
452 }
453 }
454 pub fn end_nested(mut self) -> Prev {
455 let mut prev = self.prev.take().unwrap();
456 if let Some(header_offset) = &self.header_offset {
457 finalize_nested_header(prev.as_rec_mut(), *header_offset);
458 }
459 prev
460 }
461 #[doc = "The enum binder\\_driver\\_return\\_protocol returned to the sender\\."]
462 pub fn push_error(mut self, value: u32) -> Self {
463 push_header(self.as_rec_mut(), 1u16, 4 as u16);
464 self.as_rec_mut().extend(value.to_ne_bytes());
465 self
466 }
467 #[doc = "The binder context where the transaction occurred\\."]
468 pub fn push_context(mut self, value: &CStr) -> Self {
469 push_header(
470 self.as_rec_mut(),
471 2u16,
472 value.to_bytes_with_nul().len() as u16,
473 );
474 self.as_rec_mut().extend(value.to_bytes_with_nul());
475 self
476 }
477 #[doc = "The binder context where the transaction occurred\\."]
478 pub fn push_context_bytes(mut self, value: &[u8]) -> Self {
479 push_header(self.as_rec_mut(), 2u16, (value.len() + 1) as u16);
480 self.as_rec_mut().extend(value);
481 self.as_rec_mut().push(0);
482 self
483 }
484 #[doc = "The PID of the sender process\\."]
485 pub fn push_from_pid(mut self, value: u32) -> Self {
486 push_header(self.as_rec_mut(), 3u16, 4 as u16);
487 self.as_rec_mut().extend(value.to_ne_bytes());
488 self
489 }
490 #[doc = "The TID of the sender thread\\."]
491 pub fn push_from_tid(mut self, value: u32) -> Self {
492 push_header(self.as_rec_mut(), 4u16, 4 as u16);
493 self.as_rec_mut().extend(value.to_ne_bytes());
494 self
495 }
496 #[doc = "The PID of the recipient process\\. This attribute may not be present\nif the target could not be determined\\.\n"]
497 pub fn push_to_pid(mut self, value: u32) -> Self {
498 push_header(self.as_rec_mut(), 5u16, 4 as u16);
499 self.as_rec_mut().extend(value.to_ne_bytes());
500 self
501 }
502 #[doc = "The TID of the recipient thread\\. This attribute may not be present\nif the target could not be determined\\.\n"]
503 pub fn push_to_tid(mut self, value: u32) -> Self {
504 push_header(self.as_rec_mut(), 6u16, 4 as u16);
505 self.as_rec_mut().extend(value.to_ne_bytes());
506 self
507 }
508 #[doc = "When present, indicates the failed transaction is a reply\\."]
509 pub fn push_is_reply(mut self, value: ()) -> Self {
510 push_header(self.as_rec_mut(), 7u16, 0 as u16);
511 self
512 }
513 #[doc = "The bitmask of enum transaction\\_flags from the transaction\\."]
514 pub fn push_flags(mut self, value: u32) -> Self {
515 push_header(self.as_rec_mut(), 8u16, 4 as u16);
516 self.as_rec_mut().extend(value.to_ne_bytes());
517 self
518 }
519 #[doc = "The application\\-defined code from the transaction\\."]
520 pub fn push_code(mut self, value: u32) -> Self {
521 push_header(self.as_rec_mut(), 9u16, 4 as u16);
522 self.as_rec_mut().extend(value.to_ne_bytes());
523 self
524 }
525 #[doc = "The transaction payload size in bytes\\."]
526 pub fn push_data_size(mut self, value: u32) -> Self {
527 push_header(self.as_rec_mut(), 10u16, 4 as u16);
528 self.as_rec_mut().extend(value.to_ne_bytes());
529 self
530 }
531}
532impl<Prev: Rec> Drop for PushReport<Prev> {
533 fn drop(&mut self) {
534 if let Some(prev) = &mut self.prev {
535 if let Some(header_offset) = &self.header_offset {
536 finalize_nested_header(prev.as_rec_mut(), *header_offset);
537 }
538 }
539 }
540}
541#[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"]
542#[derive(Debug)]
543pub struct OpReportNotif;
544impl OpReportNotif {
545 pub const CMD: u8 = 1u8;
546 pub fn decode_notif<'a>(buf: &'a [u8]) -> IterableReport<'a> {
547 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
548 IterableReport::with_loc(attrs, buf.as_ptr() as usize)
549 }
550}
551pub struct NotifGroup;
552impl NotifGroup {
553 #[doc = "Notifications:\n- [`OpReportNotif`]\n"]
554 pub const REPORT: &str = "report";
555 #[doc = "Notifications:\n- [`OpReportNotif`]\n"]
556 pub const REPORT_CSTR: &CStr = c"report";
557}
558#[cfg(test)]
559mod generated_tests {
560 use super::*;
561 #[test]
562 fn tests() {
563 let _ = IterableReport::get_code;
564 let _ = IterableReport::get_context;
565 let _ = IterableReport::get_data_size;
566 let _ = IterableReport::get_error;
567 let _ = IterableReport::get_flags;
568 let _ = IterableReport::get_from_pid;
569 let _ = IterableReport::get_from_tid;
570 let _ = IterableReport::get_is_reply;
571 let _ = IterableReport::get_to_pid;
572 let _ = IterableReport::get_to_tid;
573 let _ = OpReportNotif;
574 }
575}