Skip to main content

netlink_bindings/binder/
mod.rs

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}