1use kernel::{
12 alloc::{self, AllocError},
13 error::to_result,
14 prelude::*,
15 transmute::AsBytes,
16 types::Opaque,
17 ThisModule,
18};
19
20use core::{
21 mem::ManuallyDrop,
22 ptr::NonNull, };
24
25pub const GENLMSG_DEFAULT_SIZE: usize = bindings::GENLMSG_DEFAULT_SIZE;
27
28pub struct NetlinkSkBuff {
37 skb: NonNull<kernel::bindings::sk_buff>,
38}
39
40impl NetlinkSkBuff {
41 pub fn new(size: usize, flags: alloc::Flags) -> Result<NetlinkSkBuff, AllocError> {
43 let skb = unsafe { bindings::genlmsg_new(size, flags.as_raw()) };
45 let skb = NonNull::new(skb).ok_or(AllocError)?;
46 Ok(NetlinkSkBuff { skb })
47 }
48
49 pub fn genlmsg_put(
51 self,
52 portid: u32,
53 seq: u32,
54 family: &'static Family,
55 cmd: u8,
56 ) -> Result<GenlMsg, AllocError> {
57 let skb = self.skb.as_ptr();
58 let hdr = unsafe { bindings::genlmsg_put(skb, portid, seq, family.as_raw(), 0, cmd) };
60 let hdr = NonNull::new(hdr).ok_or(AllocError)?;
61 Ok(GenlMsg { skb: self, hdr })
62 }
63}
64
65impl Drop for NetlinkSkBuff {
66 fn drop(&mut self) {
67 unsafe { bindings::nlmsg_free(self.skb.as_ptr()) }
69 }
70}
71
72pub struct GenlMsg {
78 skb: NetlinkSkBuff,
79 hdr: NonNull<c_void>,
80}
81
82impl GenlMsg {
83 #[inline]
85 fn put<T>(&mut self, attrtype: c_int, value: &T) -> Result
86 where
87 T: ?Sized + AsBytes,
88 {
89 let skb = self.skb.skb.as_ptr();
90 let len = size_of_val(value);
91 let ptr = core::ptr::from_ref(value).cast::<c_void>();
92 to_result(unsafe { bindings::nla_put(skb, attrtype, len as c_int, ptr) })
95 }
96
97 #[inline]
99 pub fn put_u32(&mut self, attrtype: c_int, value: u32) -> Result {
100 self.put(attrtype, &value)
101 }
102
103 #[inline]
105 pub fn put_string(&mut self, attrtype: c_int, value: &CStr) -> Result {
106 self.put(attrtype, value.to_bytes_with_nul())
107 }
108
109 #[inline]
111 pub fn put_flag(&mut self, attrtype: c_int) -> Result {
112 let skb = self.skb.skb.as_ptr();
113 to_result(unsafe { bindings::nla_put(skb, attrtype, 0, core::ptr::null()) })
116 }
117
118 #[inline]
120 pub fn multicast(
121 self,
122 family: &'static Family,
123 portid: u32,
124 group: u32,
125 flags: alloc::Flags,
126 ) -> Result {
127 let me = ManuallyDrop::new(self);
128 unsafe {
131 bindings::genlmsg_end(me.skb.skb.as_ptr(), me.hdr.as_ptr());
132 to_result(bindings::genlmsg_multicast(
133 family.as_raw(),
134 me.skb.skb.as_ptr(),
135 portid,
136 group,
137 flags.as_raw(),
138 ))
139 }
140 }
141}
142impl Drop for GenlMsg {
143 fn drop(&mut self) {
144 unsafe { bindings::genlmsg_cancel(self.skb.skb.as_ptr(), self.hdr.as_ptr()) };
146 }
147}
148
149struct FamilyFlags {
151 netnsok: bool,
153 parallel_ops: bool,
155}
156
157impl FamilyFlags {
158 const fn into_bitfield(self) -> bindings::__BindgenBitfieldUnit<[u8; 1]> {
160 let mut bits = 0;
166 if self.netnsok {
167 bits |= 1 << 0;
168 }
169 if self.parallel_ops {
170 bits |= 1 << 1;
171 }
172 bits = u8::from_le(bits);
174 unsafe { core::mem::transmute::<u8, bindings::__BindgenBitfieldUnit<[u8; 1]>>(bits) }
176 }
177}
178
179#[repr(transparent)]
181pub struct Family {
182 inner: Opaque<bindings::genl_family>,
183}
184
185unsafe impl Sync for Family {}
187
188impl Family {
189 pub const fn const_new(
196 module: &ThisModule,
197 name: &[u8],
198 version: u32,
199 mcgrps: &'static [MulticastGroup],
200 ) -> Family {
201 let n_mcgrps = mcgrps.len() as u8;
202 if n_mcgrps as usize != mcgrps.len() {
203 panic!("too many mcgrps");
204 }
205 let mut genl_family = bindings::genl_family {
206 version,
207 _bitfield_1: FamilyFlags {
208 netnsok: true,
209 parallel_ops: true,
210 }
211 .into_bitfield(),
212 module: module.as_ptr(),
213 mcgrps: mcgrps.as_ptr().cast(),
214 n_mcgrps,
215 ..pin_init::zeroed()
216 };
217 if CStr::from_bytes_with_nul(name).is_err() {
218 panic!("genl_family name not nul-terminated");
219 }
220 if genl_family.name.len() < name.len() {
221 panic!("genl_family name too long");
222 }
223 let mut i = 0;
224 while i < name.len() {
225 genl_family.name[i] = name[i];
226 i += 1;
227 }
228 Family {
229 inner: Opaque::new(genl_family),
230 }
231 }
232
233 pub fn has_listeners(&self, group: u32) -> bool {
235 unsafe {
237 bindings::genl_has_listeners(self.as_raw(), &raw mut bindings::init_net, group) != 0
238 }
239 }
240
241 pub fn as_raw(&self) -> *mut bindings::genl_family {
243 self.inner.get()
244 }
245}
246
247#[repr(transparent)]
249pub struct MulticastGroup {
250 group: bindings::genl_multicast_group,
252}
253
254unsafe impl Sync for MulticastGroup {}
256
257impl MulticastGroup {
258 pub const fn const_new(name: &CStr) -> MulticastGroup {
262 let mut group: bindings::genl_multicast_group = pin_init::zeroed();
263
264 let name = name.to_bytes_with_nul();
265 if group.name.len() < name.len() {
266 panic!("genl_multicast_group name too long");
267 }
268 let mut i = 0;
269 while i < name.len() {
270 group.name[i] = name[i];
271 i += 1;
272 }
273
274 MulticastGroup { group }
275 }
276}
277
278pub struct Registration {
287 family: &'static Family,
288}
289
290impl Family {
291 pub fn register(&'static self) -> Result<Registration> {
293 to_result(unsafe { bindings::genl_register_family(self.as_raw()) })?;
296 Ok(Registration { family: self })
297 }
298}
299
300impl Drop for Registration {
301 fn drop(&mut self) {
302 unsafe { bindings::genl_unregister_family(self.family.as_raw()) };
306 }
307}
308
309#[macros::kunit_tests(rust_netlink)]
310mod tests {
311 use super::*;
312
313 #[test]
314 fn test_family_flags_bitfield() {
315 for netnsok in [false, true] {
316 for parallel_ops in [false, true] {
317 let mut b_fam = bindings::genl_family {
318 ..Default::default()
319 };
320 b_fam.set_netnsok(if netnsok { 1 } else { 0 });
321 b_fam.set_parallel_ops(if parallel_ops { 1 } else { 0 });
322
323 let c_bitfield = FamilyFlags {
324 netnsok,
325 parallel_ops,
326 }
327 .into_bitfield();
328
329 let b_val: u8 = unsafe { core::mem::transmute(b_fam._bitfield_1) };
331 let c_val: u8 = unsafe { core::mem::transmute(c_bitfield) };
333 assert_eq!(b_val, c_val);
334 }
335 }
336 }
337}