Skip to content

Commit 6f6ed44

Browse files
committed
Add support for Netlink socket addresses
1 parent c00ea68 commit 6f6ed44

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;
@@ -225,6 +227,17 @@ pub(crate) unsafe fn read_sockaddr(
225227
u32::from_be(decode.sxdp_shared_umem_fd),
226228
)))
227229
}
230+
#[cfg(target_os = "linux")]
231+
c::AF_NETLINK => {
232+
if len < size_of::<c::sockaddr_nl>() {
233+
return Err(io::Errno::INVAL);
234+
}
235+
let decode = &*storage.cast::<c::sockaddr_nl>();
236+
Ok(SocketAddrAny::Netlink(SocketAddrNetlink::new(
237+
decode.nl_pid,
238+
decode.nl_groups,
239+
)))
240+
}
228241
_ => Err(io::Errno::INVAL),
229242
}
230243
}
@@ -351,6 +364,12 @@ unsafe fn inner_read_sockaddr_os(
351364
u32::from_be(decode.sxdp_shared_umem_fd),
352365
))
353366
}
367+
#[cfg(target_os = "linux")]
368+
c::AF_NETLINK => {
369+
assert!(len >= size_of::<c::sockaddr_nl>());
370+
let decode = &*storage.cast::<c::sockaddr_nl>();
371+
SocketAddrAny::Netlink(SocketAddrNetlink::new(decode.nl_pid, decode.nl_groups))
372+
}
354373
other => unimplemented!("{:?}", other),
355374
}
356375
}

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
}
@@ -219,6 +232,12 @@ pub(crate) unsafe fn read_sockaddr_os(
219232
u32::from_be(decode.sxdp_shared_umem_fd),
220233
))
221234
}
235+
#[cfg(target_os = "linux")]
236+
c::AF_NETLINK => {
237+
assert!(len >= size_of::<c::sockaddr_nl>());
238+
let decode = &*storage.cast::<c::sockaddr_nl>();
239+
SocketAddrAny::Netlink(SocketAddrNetlink::new(decode.nl_pid, decode.nl_groups))
240+
}
222241
other => unimplemented!("{:?}", other),
223242
}
224243
}

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(f),
124131
#[cfg(target_os = "linux")]
125132
Self::Xdp(xdp) => xdp.fmt(f),
133+
#[cfg(target_os = "linux")]
134+
Self::Netlink(nl) => nl.fmt(f),
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
@@ -945,6 +945,8 @@ pub mod netlink {
945945
use {
946946
super::{new_raw_protocol, Protocol},
947947
crate::backend::c,
948+
crate::net::{socket_address::call_with_sockaddr, SockAddr, SockAddrRaw},
949+
core::mem,
948950
};
949951

950952
/// `NETLINK_UNUSED`
@@ -1054,6 +1056,66 @@ pub mod netlink {
10541056
/// `NETLINK_GET_STRICT_CHK`
10551057
#[cfg(linux_kernel)]
10561058
pub const GET_STRICT_CHK: Protocol = Protocol(new_raw_protocol(c::NETLINK_GET_STRICT_CHK as _));
1059+
1060+
/// A Netlink socket address.
1061+
///
1062+
/// Used to bind to a Netlink socket.
1063+
///
1064+
/// Not ABI compatible with `struct sockaddr_nl`
1065+
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
1066+
#[cfg(linux_kernel)]
1067+
pub struct SocketAddrNetlink {
1068+
/// Port ID
1069+
pid: u32,
1070+
1071+
/// Multicast groups mask
1072+
groups: u32,
1073+
}
1074+
1075+
#[cfg(linux_kernel)]
1076+
impl SocketAddrNetlink {
1077+
/// Construct a netlink address
1078+
#[inline]
1079+
pub fn new(pid: u32, groups: u32) -> Self {
1080+
Self { pid, groups }
1081+
}
1082+
1083+
/// Return port id.
1084+
#[inline]
1085+
pub fn pid(&self) -> u32 {
1086+
self.pid
1087+
}
1088+
1089+
/// Set port id.
1090+
#[inline]
1091+
pub fn set_pid(&mut self, pid: u32) {
1092+
self.pid = pid;
1093+
}
1094+
1095+
/// Return multicast groups mask.
1096+
#[inline]
1097+
pub fn groups(&self) -> u32 {
1098+
self.groups
1099+
}
1100+
1101+
/// Set multicast groups mask.
1102+
#[inline]
1103+
pub fn set_groups(&mut self, groups: u32) {
1104+
self.groups = groups;
1105+
}
1106+
}
1107+
1108+
#[cfg(linux_kernel)]
1109+
#[allow(unsafe_code)]
1110+
unsafe impl SockAddr for SocketAddrNetlink {
1111+
fn with_sockaddr<R>(&self, f: impl FnOnce(*const SockAddrRaw, usize) -> R) -> R {
1112+
let mut addr: c::sockaddr_nl = unsafe { mem::zeroed() };
1113+
addr.nl_family = c::AF_NETLINK as _;
1114+
addr.nl_pid = self.pid;
1115+
addr.nl_groups = self.groups;
1116+
call_with_sockaddr(&addr, f)
1117+
}
1118+
}
10571119
}
10581120

10591121
/// `ETH_P_*` constants.

0 commit comments

Comments
 (0)