Skip to main content

netlink_bindings/lockd/
mod.rs

1#![doc = "lockd configuration 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 = "lockd";
17pub const PROTONAME_CSTR: &CStr = c"lockd";
18#[derive(Clone)]
19pub enum Server {
20    Gracetime(u32),
21    TcpPort(u16),
22    UdpPort(u16),
23}
24impl<'a> IterableServer<'a> {
25    pub fn get_gracetime(&self) -> Result<u32, ErrorContext> {
26        let mut iter = self.clone();
27        iter.pos = 0;
28        for attr in iter {
29            if let Ok(Server::Gracetime(val)) = attr {
30                return Ok(val);
31            }
32        }
33        Err(ErrorContext::new_missing(
34            "Server",
35            "Gracetime",
36            self.orig_loc,
37            self.buf.as_ptr() as usize,
38        ))
39    }
40    pub fn get_tcp_port(&self) -> Result<u16, ErrorContext> {
41        let mut iter = self.clone();
42        iter.pos = 0;
43        for attr in iter {
44            if let Ok(Server::TcpPort(val)) = attr {
45                return Ok(val);
46            }
47        }
48        Err(ErrorContext::new_missing(
49            "Server",
50            "TcpPort",
51            self.orig_loc,
52            self.buf.as_ptr() as usize,
53        ))
54    }
55    pub fn get_udp_port(&self) -> Result<u16, ErrorContext> {
56        let mut iter = self.clone();
57        iter.pos = 0;
58        for attr in iter {
59            if let Ok(Server::UdpPort(val)) = attr {
60                return Ok(val);
61            }
62        }
63        Err(ErrorContext::new_missing(
64            "Server",
65            "UdpPort",
66            self.orig_loc,
67            self.buf.as_ptr() as usize,
68        ))
69    }
70}
71impl Server {
72    pub fn new<'a>(buf: &'a [u8]) -> IterableServer<'a> {
73        IterableServer::with_loc(buf, buf.as_ptr() as usize)
74    }
75    fn attr_from_type(r#type: u16) -> Option<&'static str> {
76        let res = match r#type {
77            1u16 => "Gracetime",
78            2u16 => "TcpPort",
79            3u16 => "UdpPort",
80            _ => return None,
81        };
82        Some(res)
83    }
84}
85#[derive(Clone, Copy, Default)]
86pub struct IterableServer<'a> {
87    buf: &'a [u8],
88    pos: usize,
89    orig_loc: usize,
90}
91impl<'a> IterableServer<'a> {
92    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
93        Self {
94            buf,
95            pos: 0,
96            orig_loc,
97        }
98    }
99    pub fn get_buf(&self) -> &'a [u8] {
100        self.buf
101    }
102}
103impl<'a> Iterator for IterableServer<'a> {
104    type Item = Result<Server, ErrorContext>;
105    fn next(&mut self) -> Option<Self::Item> {
106        let mut pos;
107        let mut r#type;
108        loop {
109            pos = self.pos;
110            r#type = None;
111            if self.buf.len() == self.pos {
112                return None;
113            }
114            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
115                self.pos = self.buf.len();
116                break;
117            };
118            r#type = Some(header.r#type);
119            let res = match header.r#type {
120                1u16 => Server::Gracetime({
121                    let res = parse_u32(next);
122                    let Some(val) = res else { break };
123                    val
124                }),
125                2u16 => Server::TcpPort({
126                    let res = parse_u16(next);
127                    let Some(val) = res else { break };
128                    val
129                }),
130                3u16 => Server::UdpPort({
131                    let res = parse_u16(next);
132                    let Some(val) = res else { break };
133                    val
134                }),
135                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
136                n => continue,
137            };
138            return Some(Ok(res));
139        }
140        Some(Err(ErrorContext::new(
141            "Server",
142            r#type.and_then(|t| Server::attr_from_type(t)),
143            self.orig_loc,
144            self.buf.as_ptr().wrapping_add(pos) as usize,
145        )))
146    }
147}
148impl std::fmt::Debug for IterableServer<'_> {
149    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150        let mut fmt = f.debug_struct("Server");
151        for attr in self.clone() {
152            let attr = match attr {
153                Ok(a) => a,
154                Err(err) => {
155                    fmt.finish()?;
156                    f.write_str("Err(")?;
157                    err.fmt(f)?;
158                    return f.write_str(")");
159                }
160            };
161            match attr {
162                Server::Gracetime(val) => fmt.field("Gracetime", &val),
163                Server::TcpPort(val) => fmt.field("TcpPort", &val),
164                Server::UdpPort(val) => fmt.field("UdpPort", &val),
165            };
166        }
167        fmt.finish()
168    }
169}
170impl IterableServer<'_> {
171    pub fn lookup_attr(
172        &self,
173        offset: usize,
174        missing_type: Option<u16>,
175    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
176        let mut stack = Vec::new();
177        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
178        if missing_type.is_some() && cur == offset {
179            stack.push(("Server", offset));
180            return (stack, missing_type.and_then(|t| Server::attr_from_type(t)));
181        }
182        if cur > offset || cur + self.buf.len() < offset {
183            return (stack, None);
184        }
185        let mut attrs = self.clone();
186        let mut last_off = cur + attrs.pos;
187        while let Some(attr) = attrs.next() {
188            let Ok(attr) = attr else { break };
189            match attr {
190                Server::Gracetime(val) => {
191                    if last_off == offset {
192                        stack.push(("Gracetime", last_off));
193                        break;
194                    }
195                }
196                Server::TcpPort(val) => {
197                    if last_off == offset {
198                        stack.push(("TcpPort", last_off));
199                        break;
200                    }
201                }
202                Server::UdpPort(val) => {
203                    if last_off == offset {
204                        stack.push(("UdpPort", last_off));
205                        break;
206                    }
207                }
208                _ => {}
209            };
210            last_off = cur + attrs.pos;
211        }
212        if !stack.is_empty() {
213            stack.push(("Server", cur));
214        }
215        (stack, None)
216    }
217}
218pub struct PushServer<Prev: Rec> {
219    pub(crate) prev: Option<Prev>,
220    pub(crate) header_offset: Option<usize>,
221}
222impl<Prev: Rec> Rec for PushServer<Prev> {
223    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
224        self.prev.as_mut().unwrap().as_rec_mut()
225    }
226    fn as_rec(&self) -> &Vec<u8> {
227        self.prev.as_ref().unwrap().as_rec()
228    }
229}
230impl<Prev: Rec> PushServer<Prev> {
231    pub fn new(prev: Prev) -> Self {
232        Self {
233            prev: Some(prev),
234            header_offset: None,
235        }
236    }
237    pub fn end_nested(mut self) -> Prev {
238        let mut prev = self.prev.take().unwrap();
239        if let Some(header_offset) = &self.header_offset {
240            finalize_nested_header(prev.as_rec_mut(), *header_offset);
241        }
242        prev
243    }
244    pub fn push_gracetime(mut self, value: u32) -> Self {
245        push_header(self.as_rec_mut(), 1u16, 4 as u16);
246        self.as_rec_mut().extend(value.to_ne_bytes());
247        self
248    }
249    pub fn push_tcp_port(mut self, value: u16) -> Self {
250        push_header(self.as_rec_mut(), 2u16, 2 as u16);
251        self.as_rec_mut().extend(value.to_ne_bytes());
252        self
253    }
254    pub fn push_udp_port(mut self, value: u16) -> Self {
255        push_header(self.as_rec_mut(), 3u16, 2 as u16);
256        self.as_rec_mut().extend(value.to_ne_bytes());
257        self
258    }
259}
260impl<Prev: Rec> Drop for PushServer<Prev> {
261    fn drop(&mut self) {
262        if let Some(prev) = &mut self.prev {
263            if let Some(header_offset) = &self.header_offset {
264                finalize_nested_header(prev.as_rec_mut(), *header_offset);
265            }
266        }
267    }
268}
269#[doc = "set the lockd server parameters\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_gracetime()](PushServer::push_gracetime)\n- [.push_tcp_port()](PushServer::push_tcp_port)\n- [.push_udp_port()](PushServer::push_udp_port)\n\n"]
270#[derive(Debug)]
271pub struct OpServerSetDo<'r> {
272    request: Request<'r>,
273}
274impl<'r> OpServerSetDo<'r> {
275    pub fn new(mut request: Request<'r>) -> Self {
276        Self::write_header(request.buf_mut());
277        Self { request: request }
278    }
279    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushServer<&'buf mut Vec<u8>> {
280        Self::write_header(buf);
281        PushServer::new(buf)
282    }
283    pub fn encode(&mut self) -> PushServer<&mut Vec<u8>> {
284        PushServer::new(self.request.buf_mut())
285    }
286    pub fn into_encoder(self) -> PushServer<RequestBuf<'r>> {
287        PushServer::new(self.request.buf)
288    }
289    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableServer<'a> {
290        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
291        IterableServer::with_loc(attrs, buf.as_ptr() as usize)
292    }
293    fn write_header<Prev: Rec>(prev: &mut Prev) {
294        let mut header = BuiltinNfgenmsg::new();
295        header.cmd = 1u8;
296        header.version = 1u8;
297        prev.as_rec_mut().extend(header.as_slice());
298    }
299}
300impl NetlinkRequest for OpServerSetDo<'_> {
301    fn protocol(&self) -> Protocol {
302        Protocol::Generic("lockd".as_bytes())
303    }
304    fn flags(&self) -> u16 {
305        self.request.flags
306    }
307    fn payload(&self) -> &[u8] {
308        self.request.buf()
309    }
310    type ReplyType<'buf> = IterableServer<'buf>;
311    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
312        Self::decode_request(buf)
313    }
314    fn lookup(
315        buf: &[u8],
316        offset: usize,
317        missing_type: Option<u16>,
318    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
319        Self::decode_request(buf).lookup_attr(offset, missing_type)
320    }
321}
322#[doc = "get the lockd server parameters\n\nReply attributes:\n- [.get_gracetime()](IterableServer::get_gracetime)\n- [.get_tcp_port()](IterableServer::get_tcp_port)\n- [.get_udp_port()](IterableServer::get_udp_port)\n\n"]
323#[derive(Debug)]
324pub struct OpServerGetDo<'r> {
325    request: Request<'r>,
326}
327impl<'r> OpServerGetDo<'r> {
328    pub fn new(mut request: Request<'r>) -> Self {
329        Self::write_header(request.buf_mut());
330        Self { request: request }
331    }
332    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushServer<&'buf mut Vec<u8>> {
333        Self::write_header(buf);
334        PushServer::new(buf)
335    }
336    pub fn encode(&mut self) -> PushServer<&mut Vec<u8>> {
337        PushServer::new(self.request.buf_mut())
338    }
339    pub fn into_encoder(self) -> PushServer<RequestBuf<'r>> {
340        PushServer::new(self.request.buf)
341    }
342    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableServer<'a> {
343        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
344        IterableServer::with_loc(attrs, buf.as_ptr() as usize)
345    }
346    fn write_header<Prev: Rec>(prev: &mut Prev) {
347        let mut header = BuiltinNfgenmsg::new();
348        header.cmd = 2u8;
349        header.version = 1u8;
350        prev.as_rec_mut().extend(header.as_slice());
351    }
352}
353impl NetlinkRequest for OpServerGetDo<'_> {
354    fn protocol(&self) -> Protocol {
355        Protocol::Generic("lockd".as_bytes())
356    }
357    fn flags(&self) -> u16 {
358        self.request.flags
359    }
360    fn payload(&self) -> &[u8] {
361        self.request.buf()
362    }
363    type ReplyType<'buf> = IterableServer<'buf>;
364    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
365        Self::decode_request(buf)
366    }
367    fn lookup(
368        buf: &[u8],
369        offset: usize,
370        missing_type: Option<u16>,
371    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
372        Self::decode_request(buf).lookup_attr(offset, missing_type)
373    }
374}
375use crate::traits::LookupFn;
376use crate::utils::RequestBuf;
377#[derive(Debug)]
378pub struct Request<'buf> {
379    buf: RequestBuf<'buf>,
380    flags: u16,
381    writeback: Option<&'buf mut Option<RequestInfo>>,
382}
383#[allow(unused)]
384#[derive(Debug, Clone)]
385pub struct RequestInfo {
386    protocol: Protocol,
387    flags: u16,
388    name: &'static str,
389    lookup: LookupFn,
390}
391impl Request<'static> {
392    pub fn new() -> Self {
393        Self::new_from_buf(Vec::new())
394    }
395    pub fn new_from_buf(buf: Vec<u8>) -> Self {
396        Self {
397            flags: 0,
398            buf: RequestBuf::Own(buf),
399            writeback: None,
400        }
401    }
402    pub fn into_buf(self) -> Vec<u8> {
403        match self.buf {
404            RequestBuf::Own(buf) => buf,
405            _ => unreachable!(),
406        }
407    }
408}
409impl<'buf> Request<'buf> {
410    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
411        buf.clear();
412        Self::new_extend(buf)
413    }
414    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
415        Self {
416            flags: 0,
417            buf: RequestBuf::Ref(buf),
418            writeback: None,
419        }
420    }
421    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
422        let Some(writeback) = &mut self.writeback else {
423            return;
424        };
425        **writeback = Some(RequestInfo {
426            protocol,
427            flags: self.flags,
428            name,
429            lookup,
430        })
431    }
432    pub fn buf(&self) -> &Vec<u8> {
433        self.buf.buf()
434    }
435    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
436        self.buf.buf_mut()
437    }
438    #[doc = "Set `NLM_F_CREATE` flag"]
439    pub fn set_create(mut self) -> Self {
440        self.flags |= consts::NLM_F_CREATE as u16;
441        self
442    }
443    #[doc = "Set `NLM_F_EXCL` flag"]
444    pub fn set_excl(mut self) -> Self {
445        self.flags |= consts::NLM_F_EXCL as u16;
446        self
447    }
448    #[doc = "Set `NLM_F_REPLACE` flag"]
449    pub fn set_replace(mut self) -> Self {
450        self.flags |= consts::NLM_F_REPLACE as u16;
451        self
452    }
453    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
454    pub fn set_change(self) -> Self {
455        self.set_create().set_replace()
456    }
457    #[doc = "Set `NLM_F_APPEND` flag"]
458    pub fn set_append(mut self) -> Self {
459        self.flags |= consts::NLM_F_APPEND as u16;
460        self
461    }
462    #[doc = "Set `self.flags |= flags`"]
463    pub fn set_flags(mut self, flags: u16) -> Self {
464        self.flags |= flags;
465        self
466    }
467    #[doc = "Set `self.flags ^= self.flags & flags`"]
468    pub fn unset_flags(mut self, flags: u16) -> Self {
469        self.flags ^= self.flags & flags;
470        self
471    }
472    #[doc = "set the lockd server parameters\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_gracetime()](PushServer::push_gracetime)\n- [.push_tcp_port()](PushServer::push_tcp_port)\n- [.push_udp_port()](PushServer::push_udp_port)\n\n"]
473    pub fn op_server_set_do(self) -> OpServerSetDo<'buf> {
474        let mut res = OpServerSetDo::new(self);
475        res.request
476            .do_writeback(res.protocol(), "op-server-set-do", OpServerSetDo::lookup);
477        res
478    }
479    #[doc = "get the lockd server parameters\n\nReply attributes:\n- [.get_gracetime()](IterableServer::get_gracetime)\n- [.get_tcp_port()](IterableServer::get_tcp_port)\n- [.get_udp_port()](IterableServer::get_udp_port)\n\n"]
480    pub fn op_server_get_do(self) -> OpServerGetDo<'buf> {
481        let mut res = OpServerGetDo::new(self);
482        res.request
483            .do_writeback(res.protocol(), "op-server-get-do", OpServerGetDo::lookup);
484        res
485    }
486}
487#[cfg(test)]
488mod generated_tests {
489    use super::*;
490    #[test]
491    fn tests() {
492        let _ = IterableServer::get_gracetime;
493        let _ = IterableServer::get_tcp_port;
494        let _ = IterableServer::get_udp_port;
495        let _ = PushServer::<&mut Vec<u8>>::push_gracetime;
496        let _ = PushServer::<&mut Vec<u8>>::push_tcp_port;
497        let _ = PushServer::<&mut Vec<u8>>::push_udp_port;
498    }
499}