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: Pusher> {
219 pub(crate) prev: Option<Prev>,
220 pub(crate) header_offset: Option<usize>,
221}
222impl<Prev: Pusher> Pusher for PushServer<Prev> {
223 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
224 self.prev.as_mut().unwrap().as_vec_mut()
225 }
226 fn as_vec(&self) -> &Vec<u8> {
227 self.prev.as_ref().unwrap().as_vec()
228 }
229}
230impl<Prev: Pusher> 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_vec_mut(), *header_offset);
241 }
242 prev
243 }
244 pub fn push_gracetime(mut self, value: u32) -> Self {
245 push_header(self.as_vec_mut(), 1u16, 4 as u16);
246 self.as_vec_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_vec_mut(), 2u16, 2 as u16);
251 self.as_vec_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_vec_mut(), 3u16, 2 as u16);
256 self.as_vec_mut().extend(value.to_ne_bytes());
257 self
258 }
259}
260impl<Prev: Pusher> 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_vec_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: Pusher>(prev: &mut Prev) {
294 let mut header = BuiltinNfgenmsg::new();
295 header.cmd = 1u8;
296 header.version = 1u8;
297 prev.as_vec_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: Pusher>(prev: &mut Prev) {
347 let mut header = BuiltinNfgenmsg::new();
348 header.cmd = 2u8;
349 header.version = 1u8;
350 prev.as_vec_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}