Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4c1c746

Browse files
committedJan 29, 2024
Add support for Netlink socket addresses
1 parent 8533f7c commit 4c1c746

File tree

4 files changed

+119
-4
lines changed

4 files changed

+119
-4
lines changed
 

‎src/backend/libc/net/read_sockaddr.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ use crate::backend::c;
99
use crate::ffi::CStr;
1010
use crate::io;
1111
#[cfg(target_os = "linux")]
12-
use crate::net::xdp::{SockaddrXdpFlags, SocketAddrXdp};
12+
use crate::net::{
13+
netlink::SocketAddrNetlink,
14+
xdp::{SockaddrXdpFlags, SocketAddrXdp},
15+
};
1316
use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrV4, SocketAddrV6};
1417
use core::mem::size_of;
1518

@@ -208,6 +211,17 @@ pub(crate) unsafe fn read_sockaddr(
208211
u32::from_be(decode.sxdp_shared_umem_fd),
209212
)))
210213
}
214+
#[cfg(target_os = "linux")]
215+
c::AF_NETLINK => {
216+
if len < size_of::<c::sockaddr_nl>() {
217+
return Err(io::Errno::INVAL);
218+
}
219+
let decode = &*storage.cast::<c::sockaddr_nl>();
220+
Ok(SocketAddrAny::Netlink(SocketAddrNetlink::new(
221+
decode.nl_pid,
222+
decode.nl_groups,
223+
)))
224+
}
211225
_ => Err(io::Errno::INVAL),
212226
}
213227
}
@@ -327,6 +341,12 @@ unsafe fn inner_read_sockaddr_os(
327341
u32::from_be(decode.sxdp_shared_umem_fd),
328342
))
329343
}
344+
#[cfg(target_os = "linux")]
345+
c::AF_NETLINK => {
346+
assert!(len >= size_of::<c::sockaddr_nl>());
347+
let decode = &*storage.cast::<c::sockaddr_nl>();
348+
SocketAddrAny::Netlink(SocketAddrNetlink::new(decode.nl_pid, decode.nl_groups))
349+
}
330350
other => unimplemented!("{:?}", other),
331351
}
332352
}

‎src/backend/linux_raw/net/read_sockaddr.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
use crate::backend::c;
66
use crate::io;
77
#[cfg(target_os = "linux")]
8-
use crate::net::xdp::{SockaddrXdpFlags, SocketAddrXdp};
8+
use crate::net::{
9+
netlink::SocketAddrNetlink,
10+
xdp::{SockaddrXdpFlags, SocketAddrXdp},
11+
};
912
use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6};
1013
use core::mem::size_of;
1114
use core::slice;
@@ -127,6 +130,17 @@ pub(crate) unsafe fn read_sockaddr(
127130
u32::from_be(decode.sxdp_shared_umem_fd),
128131
)))
129132
}
133+
#[cfg(target_os = "linux")]
134+
c::AF_NETLINK => {
135+
if len < size_of::<c::sockaddr_nl>() {
136+
return Err(io::Errno::INVAL);
137+
}
138+
let decode = &*storage.cast::<c::sockaddr_nl>();
139+
Ok(SocketAddrAny::Netlink(SocketAddrNetlink::new(
140+
decode.nl_pid,
141+
decode.nl_groups,
142+
)))
143+
}
130144
_ => Err(io::Errno::NOTSUP),
131145
}
132146
}
@@ -216,6 +230,12 @@ pub(crate) unsafe fn read_sockaddr_os(storage: *const c::sockaddr, len: usize) -
216230
u32::from_be(decode.sxdp_shared_umem_fd),
217231
))
218232
}
233+
#[cfg(target_os = "linux")]
234+
c::AF_NETLINK => {
235+
assert!(len >= size_of::<c::sockaddr_nl>());
236+
let decode = &*storage.cast::<c::sockaddr_nl>();
237+
SocketAddrAny::Netlink(SocketAddrNetlink::new(decode.nl_pid, decode.nl_groups))
238+
}
219239
other => unimplemented!("{:?}", other),
220240
}
221241
}

‎src/net/socket_addr_any.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
#![allow(unsafe_code)]
1111

1212
use crate::backend::c;
13-
#[cfg(target_os = "linux")]
14-
use crate::net::xdp::SocketAddrXdp;
1513
#[cfg(unix)]
1614
use crate::net::SocketAddrUnix;
15+
#[cfg(target_os = "linux")]
16+
use crate::net::{netlink::SocketAddrNetlink, xdp::SocketAddrXdp};
1717
use crate::net::{AddressFamily, SocketAddr, SocketAddrV4, SocketAddrV6};
1818
use crate::{backend, io};
1919
#[cfg(feature = "std")]
@@ -39,6 +39,9 @@ pub enum SocketAddrAny {
3939
/// `struct sockaddr_xdp`
4040
#[cfg(target_os = "linux")]
4141
Xdp(SocketAddrXdp),
42+
/// `struct sockaddr_nl`
43+
#[cfg(target_os = "linux")]
44+
Netlink(SocketAddrNetlink),
4245
}
4346

4447
impl From<SocketAddr> for SocketAddrAny {
@@ -84,6 +87,8 @@ impl SocketAddrAny {
8487
Self::Unix(_) => AddressFamily::UNIX,
8588
#[cfg(target_os = "linux")]
8689
Self::Xdp(_) => AddressFamily::XDP,
90+
#[cfg(target_os = "linux")]
91+
Self::Netlink(_) => AddressFamily::NETLINK,
8792
}
8893
}
8994

@@ -103,6 +108,8 @@ impl SocketAddrAny {
103108
SocketAddrAny::Unix(a) => a.write_sockaddr(storage),
104109
#[cfg(target_os = "linux")]
105110
SocketAddrAny::Xdp(a) => a.write_sockaddr(storage),
111+
#[cfg(target_os = "linux")]
112+
SocketAddrAny::Netlink(a) => a.write_sockaddr(storage),
106113
}
107114
}
108115

@@ -128,6 +135,8 @@ impl fmt::Debug for SocketAddrAny {
128135
Self::Unix(unix) => unix.fmt(fmt),
129136
#[cfg(target_os = "linux")]
130137
Self::Xdp(xdp) => xdp.fmt(fmt),
138+
#[cfg(target_os = "linux")]
139+
Self::Netlink(nl) => nl.fmt(fmt),
131140
}
132141
}
133142
}
@@ -158,6 +167,8 @@ unsafe impl SocketAddress for SocketAddrAny {
158167
Self::Unix(a) => a.with_sockaddr(f),
159168
#[cfg(target_os = "linux")]
160169
Self::Xdp(a) => a.with_sockaddr(f),
170+
#[cfg(target_os = "linux")]
171+
Self::Netlink(a) => a.with_sockaddr(f),
161172
}
162173
}
163174
}

‎src/net/types.rs

+64
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,8 @@ pub mod netlink {
915915
use {
916916
super::{new_raw_protocol, Protocol},
917917
crate::backend::c,
918+
crate::net::SocketAddress,
919+
core::mem,
918920
};
919921

920922
/// `NETLINK_UNUSED`
@@ -1024,6 +1026,68 @@ pub mod netlink {
10241026
/// `NETLINK_GET_STRICT_CHK`
10251027
#[cfg(linux_kernel)]
10261028
pub const GET_STRICT_CHK: Protocol = Protocol(new_raw_protocol(c::NETLINK_GET_STRICT_CHK as _));
1029+
1030+
/// A Netlink socket address.
1031+
///
1032+
/// Used to bind to a Netlink socket.
1033+
///
1034+
/// Not ABI compatible with `struct sockaddr_nl`
1035+
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
1036+
#[cfg(linux_kernel)]
1037+
pub struct SocketAddrNetlink {
1038+
/// Port ID
1039+
pid: u32,
1040+
1041+
/// Multicast groups mask
1042+
groups: u32,
1043+
}
1044+
1045+
#[cfg(linux_kernel)]
1046+
impl SocketAddrNetlink {
1047+
/// Construct a netlink address
1048+
#[inline]
1049+
pub fn new(pid: u32, groups: u32) -> Self {
1050+
Self { pid, groups }
1051+
}
1052+
1053+
/// Return port id.
1054+
#[inline]
1055+
pub fn pid(&self) -> u32 {
1056+
self.pid
1057+
}
1058+
1059+
/// Set port id.
1060+
#[inline]
1061+
pub fn set_pid(&mut self, pid: u32) {
1062+
self.pid = pid;
1063+
}
1064+
1065+
/// Return multicast groups mask.
1066+
#[inline]
1067+
pub fn groups(&self) -> u32 {
1068+
self.groups
1069+
}
1070+
1071+
/// Set multicast groups mask.
1072+
#[inline]
1073+
pub fn set_groups(&mut self, groups: u32) {
1074+
self.groups = groups;
1075+
}
1076+
}
1077+
1078+
#[cfg(linux_kernel)]
1079+
#[allow(unsafe_code)]
1080+
unsafe impl SocketAddress for SocketAddrNetlink {
1081+
type CSockAddr = c::sockaddr_nl;
1082+
1083+
fn encode(&self) -> Self::CSockAddr {
1084+
let mut addr: c::sockaddr_nl = unsafe { mem::zeroed() };
1085+
addr.nl_family = c::AF_NETLINK as _;
1086+
addr.nl_pid = self.pid;
1087+
addr.nl_groups = self.groups;
1088+
addr
1089+
}
1090+
}
10271091
}
10281092

10291093
/// `ETH_P_*` constants.

0 commit comments

Comments
 (0)
Please sign in to comment.