1use kernel::{
12 alloc::{self, AllocError},
13 error::to_result,
14 num::casts::u16_as_usize,
15 prelude::*,
16 types::Opaque,
17 ThisModule,
18};
19
20use core::{
21 mem::ManuallyDrop,
22 ptr::NonNull, };
24
25use zerocopy::{
26 Immutable,
27 IntoBytes, };
29
30pub const GENLMSG_DEFAULT_SIZE: usize = bindings::GENLMSG_DEFAULT_SIZE;
32
33pub struct NetlinkSkBuff {
42 skb: NonNull<kernel::bindings::sk_buff>,
43}
44
45impl NetlinkSkBuff {
46 pub fn new(size: usize, flags: alloc::Flags) -> Result<NetlinkSkBuff, AllocError> {
48 let skb = unsafe { bindings::genlmsg_new(size, flags.as_raw()) };
50 let skb = NonNull::new(skb).ok_or(AllocError)?;
51 Ok(NetlinkSkBuff { skb })
52 }
53
54 pub fn genlmsg_put(
56 self,
57 portid: u32,
58 seq: u32,
59 family: &'static Family,
60 cmd: u8,
61 ) -> Result<GenlMsg, AllocError> {
62 let skb = self.skb.as_ptr();
63 let hdr = unsafe { bindings::genlmsg_put(skb, portid, seq, family.as_raw(), 0, cmd) };
65 let hdr = NonNull::new(hdr).ok_or(AllocError)?;
66 Ok(GenlMsg { skb: self, hdr })
67 }
68}
69
70impl Drop for NetlinkSkBuff {
71 fn drop(&mut self) {
72 unsafe { bindings::nlmsg_free(self.skb.as_ptr()) }
74 }
75}
76
77pub struct GenlMsg {
83 skb: NetlinkSkBuff,
84 hdr: NonNull<c_void>,
85}
86
87impl GenlMsg {
88 #[inline]
90 fn put<T>(&mut self, attrtype: c_int, value: &T) -> Result
91 where
92 T: ?Sized + IntoBytes + Immutable,
93 {
94 const MAX_PAYLOAD_LEN: usize = u16_as_usize(u16::MAX) - size_of::<bindings::nlattr>();
98
99 let skb = self.skb.skb.as_ptr();
100 let len = size_of_val(value);
101 let ptr = core::ptr::from_ref(value).cast::<c_void>();
102 if len > MAX_PAYLOAD_LEN {
103 return Err(EMSGSIZE);
104 }
105 to_result(unsafe { bindings::nla_put(skb, attrtype, len as c_int, ptr) })
108 }
109
110 #[inline]
112 pub fn put_u32(&mut self, attrtype: c_int, value: u32) -> Result {
113 self.put(attrtype, &value)
114 }
115
116 #[inline]
118 pub fn put_string(&mut self, attrtype: c_int, value: &CStr) -> Result {
119 self.put(attrtype, value.to_bytes_with_nul())
120 }
121
122 #[inline]
124 pub fn put_flag(&mut self, attrtype: c_int) -> Result {
125 let skb = self.skb.skb.as_ptr();
126 to_result(unsafe { bindings::nla_put(skb, attrtype, 0, core::ptr::null()) })
129 }
130
131 #[inline]
133 pub fn multicast(
134 self,
135 family: &'static Family,
136 portid: u32,
137 group: u32,
138 flags: alloc::Flags,
139 ) -> Result {
140 let me = ManuallyDrop::new(self);
141 unsafe {
144 bindings::genlmsg_end(me.skb.skb.as_ptr(), me.hdr.as_ptr());
145 to_result(bindings::genlmsg_multicast(
146 family.as_raw(),
147 me.skb.skb.as_ptr(),
148 portid,
149 group,
150 flags.as_raw(),
151 ))
152 }
153 }
154}
155impl Drop for GenlMsg {
156 fn drop(&mut self) {
157 unsafe { bindings::genlmsg_cancel(self.skb.skb.as_ptr(), self.hdr.as_ptr()) };
159 }
160}
161
162struct FamilyFlags {
164 netnsok: bool,
166 parallel_ops: bool,
168}
169
170impl FamilyFlags {
171 const fn into_bitfield(self) -> bindings::__BindgenBitfieldUnit<[u8; 1]> {
173 let mut bits = 0;
179 if self.netnsok {
180 bits |= 1 << 0;
181 }
182 if self.parallel_ops {
183 bits |= 1 << 1;
184 }
185 bits = u8::from_le(bits);
187 unsafe { core::mem::transmute::<u8, bindings::__BindgenBitfieldUnit<[u8; 1]>>(bits) }
189 }
190}
191
192#[repr(transparent)]
194pub struct Family {
195 inner: Opaque<bindings::genl_family>,
196}
197
198unsafe impl Sync for Family {}
200
201impl Family {
202 pub const fn const_new(
209 module: &ThisModule,
210 name: &[u8],
211 version: u32,
212 mcgrps: &'static [MulticastGroup],
213 ) -> Family {
214 let n_mcgrps = mcgrps.len() as u8;
215 if n_mcgrps as usize != mcgrps.len() {
216 panic!("too many mcgrps");
217 }
218 let mut genl_family = bindings::genl_family {
219 version,
220 _bitfield_1: FamilyFlags {
221 netnsok: true,
222 parallel_ops: true,
223 }
224 .into_bitfield(),
225 module: module.as_ptr(),
226 mcgrps: mcgrps.as_ptr().cast(),
227 n_mcgrps,
228 ..pin_init::zeroed()
229 };
230 if CStr::from_bytes_with_nul(name).is_err() {
231 panic!("genl_family name not nul-terminated");
232 }
233 if genl_family.name.len() < name.len() {
234 panic!("genl_family name too long");
235 }
236 let mut i = 0;
237 while i < name.len() {
238 genl_family.name[i] = name[i];
239 i += 1;
240 }
241 Family {
242 inner: Opaque::new(genl_family),
243 }
244 }
245
246 pub fn has_listeners(&self, group: u32) -> bool {
248 unsafe {
250 bindings::genl_has_listeners(self.as_raw(), &raw mut bindings::init_net, group) != 0
251 }
252 }
253
254 pub fn as_raw(&self) -> *mut bindings::genl_family {
256 self.inner.get()
257 }
258}
259
260#[repr(transparent)]
262pub struct MulticastGroup {
263 group: bindings::genl_multicast_group,
265}
266
267unsafe impl Sync for MulticastGroup {}
269
270impl MulticastGroup {
271 pub const fn const_new(name: &CStr) -> MulticastGroup {
275 let mut group: bindings::genl_multicast_group = pin_init::zeroed();
276
277 let name = name.to_bytes_with_nul();
278 if group.name.len() < name.len() {
279 panic!("genl_multicast_group name too long");
280 }
281 let mut i = 0;
282 while i < name.len() {
283 group.name[i] = name[i];
284 i += 1;
285 }
286
287 MulticastGroup { group }
288 }
289}
290
291pub struct Registration {
300 family: &'static Family,
301}
302
303impl Family {
304 pub fn register(&'static self) -> Result<Registration> {
306 to_result(unsafe { bindings::genl_register_family(self.as_raw()) })?;
309 Ok(Registration { family: self })
310 }
311}
312
313impl Drop for Registration {
314 fn drop(&mut self) {
315 unsafe { bindings::genl_unregister_family(self.family.as_raw()) };
319 }
320}
321
322#[macros::kunit_tests(rust_netlink)]
323mod tests {
324 use super::*;
325
326 #[test]
327 fn test_family_flags_bitfield() {
328 for netnsok in [false, true] {
329 for parallel_ops in [false, true] {
330 let mut b_fam = bindings::genl_family {
331 ..Default::default()
332 };
333 b_fam.set_netnsok(if netnsok { 1 } else { 0 });
334 b_fam.set_parallel_ops(if parallel_ops { 1 } else { 0 });
335
336 let c_bitfield = FamilyFlags {
337 netnsok,
338 parallel_ops,
339 }
340 .into_bitfield();
341
342 let b_val: u8 = unsafe { core::mem::transmute(b_fam._bitfield_1) };
344 let c_val: u8 = unsafe { core::mem::transmute(c_bitfield) };
346 assert_eq!(b_val, c_val);
347 }
348 }
349 }
350}