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}