Skip to content

Commit 9b432db

Browse files
committed
Add support for Netlink socket addresses
1 parent c5bf5be commit 9b432db

File tree

4 files changed

+111
-0
lines changed

4 files changed

+111
-0
lines changed

src/backend/libc/net/read_sockaddr.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use crate::backend::c;
99
use crate::ffi::CStr;
1010
use crate::io;
1111
#[cfg(target_os = "linux")]
12+
use crate::net::netlink::SocketAddrNetlink;
13+
#[cfg(target_os = "linux")]
1214
use crate::net::xdp::{SockaddrXdpFlags, SocketAddrXdp};
1315
use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrV4, SocketAddrV6};
1416
use core::mem::size_of;
@@ -210,6 +212,17 @@ pub(crate) unsafe fn read_sockaddr(
210212
u32::from_be(decode.sxdp_shared_umem_fd),
211213
)))
212214
}
215+
#[cfg(target_os = "linux")]
216+
c::AF_NETLINK => {
217+
if len < size_of::<c::sockaddr_nl>() {
218+
return Err(io::Errno::INVAL);
219+
}
220+
let decode = &*storage.cast::<c::sockaddr_nl>();
221+
Ok(SocketAddrAny::Netlink(SocketAddrNetlink::new(
222+
decode.nl_pid,
223+
decode.nl_groups,
224+
)))
225+
}
213226
_ => Err(io::Errno::INVAL),
214227
}
215228
}
@@ -329,6 +342,12 @@ unsafe fn inner_read_sockaddr_os(
329342
u32::from_be(decode.sxdp_shared_umem_fd),
330343
))
331344
}
345+
#[cfg(target_os = "linux")]
346+
c::AF_NETLINK => {
347+
assert!(len >= size_of::<c::sockaddr_nl>());
348+
let decode = &*storage.cast::<c::sockaddr_nl>();
349+
SocketAddrAny::Netlink(SocketAddrNetlink::new(decode.nl_pid, decode.nl_groups))
350+
}
332351
other => unimplemented!("{:?}", other),
333352
}
334353
}

src/backend/linux_raw/net/read_sockaddr.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use crate::backend::c;
66
use crate::io;
77
#[cfg(target_os = "linux")]
8+
use crate::net::netlink::SocketAddrNetlink;
9+
#[cfg(target_os = "linux")]
810
use crate::net::xdp::{SockaddrXdpFlags, SocketAddrXdp};
911
use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6};
1012
use core::mem::size_of;
@@ -127,6 +129,17 @@ pub(crate) unsafe fn read_sockaddr(
127129
u32::from_be(decode.sxdp_shared_umem_fd),
128130
)))
129131
}
132+
#[cfg(target_os = "linux")]
133+
c::AF_NETLINK => {
134+
if len < size_of::<c::sockaddr_nl>() {
135+
return Err(io::Errno::INVAL);
136+
}
137+
let decode = &*storage.cast::<c::sockaddr_nl>();
138+
Ok(SocketAddrAny::Netlink(SocketAddrNetlink::new(
139+
decode.nl_pid,
140+
decode.nl_groups,
141+
)))
142+
}
130143
_ => Err(io::Errno::NOTSUP),
131144
}
132145
}
@@ -216,6 +229,12 @@ pub(crate) unsafe fn read_sockaddr_os(storage: *const c::sockaddr, len: usize) -
216229
u32::from_be(decode.sxdp_shared_umem_fd),
217230
))
218231
}
232+
#[cfg(target_os = "linux")]
233+
c::AF_NETLINK => {
234+
assert!(len >= size_of::<c::sockaddr_nl>());
235+
let decode = &*storage.cast::<c::sockaddr_nl>();
236+
SocketAddrAny::Netlink(SocketAddrNetlink::new(decode.nl_pid, decode.nl_groups))
237+
}
219238
other => unimplemented!("{:?}", other),
220239
}
221240
}

src/net/socket_addr_any.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
//! OS-specific socket address representations in memory.
1010
#![allow(unsafe_code)]
1111

12+
#[cfg(target_os = "linux")]
13+
use crate::net::netlink::SocketAddrNetlink;
1214
#[cfg(target_os = "linux")]
1315
use crate::net::xdp::SocketAddrXdp;
1416
#[cfg(unix)]
@@ -36,6 +38,9 @@ pub enum SocketAddrAny {
3638
/// `struct sockaddr_xdp`
3739
#[cfg(target_os = "linux")]
3840
Xdp(SocketAddrXdp),
41+
/// `struct sockaddr_nl`
42+
#[cfg(target_os = "linux")]
43+
Netlink(SocketAddrNetlink),
3944
}
4045

4146
impl From<SocketAddr> for SocketAddrAny {
@@ -81,6 +86,8 @@ impl SocketAddrAny {
8186
Self::Unix(_) => AddressFamily::UNIX,
8287
#[cfg(target_os = "linux")]
8388
Self::Xdp(_) => AddressFamily::XDP,
89+
#[cfg(target_os = "linux")]
90+
Self::Netlink(_) => AddressFamily::NETLINK,
8491
}
8592
}
8693

@@ -123,6 +130,8 @@ impl fmt::Debug for SocketAddrAny {
123130
Self::Unix(unix) => unix.fmt(fmt),
124131
#[cfg(target_os = "linux")]
125132
Self::Xdp(xdp) => xdp.fmt(fmt),
133+
#[cfg(target_os = "linux")]
134+
Self::Netlink(nl) => nl.fmt(fmt),
126135
}
127136
}
128137
}
@@ -136,6 +145,8 @@ unsafe impl SockAddr for SocketAddrAny {
136145
Self::Unix(a) => a.with_sockaddr(f),
137146
#[cfg(target_os = "linux")]
138147
Self::Xdp(a) => a.with_sockaddr(f),
148+
#[cfg(target_os = "linux")]
149+
Self::Netlink(a) => a.with_sockaddr(f),
139150
}
140151
}
141152
}

src/net/types.rs

Lines changed: 62 additions & 0 deletions
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::{socket_address::call_with_sockaddr, SockAddr, SockAddrRaw},
919+
core::mem,
918920
};
919921

920922
/// `NETLINK_UNUSED`
@@ -1024,6 +1026,66 @@ 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 SockAddr for SocketAddrNetlink {
1081+
fn with_sockaddr<R>(&self, f: impl FnOnce(*const SockAddrRaw, usize) -> R) -> R {
1082+
let mut addr: c::sockaddr_nl = unsafe { mem::zeroed() };
1083+
addr.nl_family = c::AF_NETLINK as _;
1084+
addr.nl_pid = self.pid;
1085+
addr.nl_groups = self.groups;
1086+
call_with_sockaddr(&addr, f)
1087+
}
1088+
}
10271089
}
10281090

10291091
/// `ETH_P_*` constants.

0 commit comments

Comments
 (0)