Skip to main content

netlink_bindings/binder/
mod.rs

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}