Skip to main content

netlink_bindings/lockd/
mod.rs

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