Skip to content

Commit d8b061b

Browse files
committed
refactor(s2n-quic-platform): move pktinfo checks to separate modules
1 parent 311ece3 commit d8b061b

File tree

15 files changed

+952
-568
lines changed

15 files changed

+952
-568
lines changed

quic/s2n-quic-platform/src/features.rs

+5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ type c_int = std::os::raw::c_int;
66

77
pub mod gro;
88
pub mod gso;
9+
pub mod pktinfo;
10+
pub mod pktinfo_v4;
11+
pub mod pktinfo_v6;
12+
pub mod tos;
913
pub mod tos_v4;
1014
pub mod tos_v6;
15+
1116
pub use gso::Gso;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
pub const IS_SUPPORTED: bool = super::pktinfo_v4::IS_SUPPORTED || super::pktinfo_v6::IS_SUPPORTED;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use super::c_int;
5+
use s2n_quic_core::inet::IpV4Address;
6+
7+
#[cfg(s2n_quic_platform_pktinfo)]
8+
mod pktinfo_enabled {
9+
use super::*;
10+
use crate::message::cmsg;
11+
use libc::{IPPROTO_IP, IP_PKTINFO};
12+
13+
pub const LEVEL: Option<c_int> = Some(IPPROTO_IP as _);
14+
pub const TYPE: Option<c_int> = Some(IP_PKTINFO as _);
15+
pub const SOCKOPT: Option<(c_int, c_int)> = Some((IPPROTO_IP as _, IP_PKTINFO as _));
16+
pub const CMSG_SPACE: usize = crate::message::cmsg::size_of_cmsg::<Cmsg>();
17+
18+
pub type Cmsg = libc::in_pktinfo;
19+
20+
#[inline]
21+
pub const fn is_match(level: c_int, ty: c_int) -> bool {
22+
level == IPPROTO_IP as c_int && ty == IP_PKTINFO as c_int
23+
}
24+
25+
/// # Safety
26+
///
27+
/// * The provided bytes must be aligned to `cmsghdr`
28+
#[inline]
29+
pub unsafe fn decode(bytes: &[u8]) -> Option<(IpV4Address, u32)> {
30+
let pkt_info = cmsg::decode::value_from_bytes::<Cmsg>(bytes)?;
31+
32+
// read from both fields in case only one is set and not the other
33+
//
34+
// from https://man7.org/linux/man-pages/man7/ip.7.html:
35+
//
36+
// > ipi_spec_dst is the local address
37+
// > of the packet and ipi_addr is the destination address in
38+
// > the packet header.
39+
let local_address = match (pkt_info.ipi_addr.s_addr, pkt_info.ipi_spec_dst.s_addr) {
40+
(0, v) => v.to_ne_bytes(),
41+
(v, _) => v.to_ne_bytes(),
42+
};
43+
44+
let address = IpV4Address::new(local_address);
45+
let interface = pkt_info.ipi_ifindex as _;
46+
47+
Some((address, interface))
48+
}
49+
50+
#[inline]
51+
pub fn encode(addr: &IpV4Address, local_interface: Option<u32>) -> Cmsg {
52+
let mut pkt_info = unsafe { core::mem::zeroed::<Cmsg>() };
53+
pkt_info.ipi_spec_dst.s_addr = u32::from_ne_bytes((*addr).into());
54+
if let Some(interface) = local_interface {
55+
pkt_info.ipi_ifindex = interface as _;
56+
}
57+
pkt_info
58+
}
59+
}
60+
61+
#[cfg(any(not(s2n_quic_platform_pktinfo), test))]
62+
mod pktinfo_disabled {
63+
#![cfg_attr(test, allow(dead_code))]
64+
use super::*;
65+
66+
pub const LEVEL: Option<c_int> = None;
67+
pub const TYPE: Option<c_int> = None;
68+
pub const SOCKOPT: Option<(c_int, c_int)> = None;
69+
pub const CMSG_SPACE: usize = 0;
70+
71+
pub type Cmsg = c_int;
72+
73+
#[inline]
74+
pub const fn is_match(level: c_int, ty: c_int) -> bool {
75+
let _ = level;
76+
let _ = ty;
77+
false
78+
}
79+
80+
/// # Safety
81+
///
82+
/// * The provided bytes must be aligned to `cmsghdr`
83+
pub unsafe fn decode(bytes: &[u8]) -> Option<(IpV4Address, u32)> {
84+
let _ = bytes;
85+
None
86+
}
87+
88+
#[inline]
89+
pub fn encode(addr: &IpV4Address, local_interface: Option<u32>) -> Cmsg {
90+
let _ = addr;
91+
let _ = local_interface;
92+
unimplemented!("this platform does not support pktinfo")
93+
}
94+
}
95+
96+
mod pktinfo_impl {
97+
#[cfg(not(s2n_quic_platform_pktinfo))]
98+
pub use super::pktinfo_disabled::*;
99+
#[cfg(s2n_quic_platform_pktinfo)]
100+
pub use super::pktinfo_enabled::*;
101+
}
102+
103+
pub use pktinfo_impl::*;
104+
105+
pub const IS_SUPPORTED: bool = cfg!(s2n_quic_platform_pktinfo);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use super::c_int;
5+
use s2n_quic_core::inet::IpV6Address;
6+
7+
#[cfg(s2n_quic_platform_pktinfo)]
8+
mod pktinfo_enabled {
9+
use super::*;
10+
use crate::message::cmsg;
11+
use libc::{IPPROTO_IPV6, IPV6_PKTINFO, IPV6_RECVPKTINFO};
12+
13+
pub const LEVEL: Option<c_int> = Some(IPPROTO_IPV6 as _);
14+
pub const TYPE: Option<c_int> = Some(IPV6_PKTINFO as _);
15+
pub const SOCKOPT: Option<(c_int, c_int)> = Some((IPPROTO_IPV6 as _, IPV6_RECVPKTINFO));
16+
pub const CMSG_SPACE: usize = crate::message::cmsg::size_of_cmsg::<Cmsg>();
17+
18+
pub type Cmsg = libc::in6_pktinfo;
19+
20+
#[inline]
21+
pub const fn is_match(level: c_int, ty: c_int) -> bool {
22+
level == IPPROTO_IPV6 as c_int && ty == IPV6_PKTINFO as c_int
23+
}
24+
25+
/// # Safety
26+
///
27+
/// * The provided bytes must be aligned to `cmsghdr`
28+
pub unsafe fn decode(bytes: &[u8]) -> Option<(IpV6Address, u32)> {
29+
let pkt_info = cmsg::decode::value_from_bytes::<Cmsg>(bytes)?;
30+
31+
let local_address = pkt_info.ipi6_addr.s6_addr;
32+
33+
let address = IpV6Address::new(local_address);
34+
let interface = pkt_info.ipi6_ifindex as _;
35+
36+
Some((address, interface))
37+
}
38+
39+
#[inline]
40+
pub fn encode(addr: &IpV6Address, local_interface: Option<u32>) -> Cmsg {
41+
let mut pkt_info = unsafe { core::mem::zeroed::<Cmsg>() };
42+
pkt_info.ipi6_addr.s6_addr = (*addr).into();
43+
if let Some(interface) = local_interface {
44+
pkt_info.ipi6_ifindex = interface as _;
45+
}
46+
pkt_info
47+
}
48+
}
49+
50+
#[cfg(any(not(s2n_quic_platform_pktinfo), test))]
51+
mod pktinfo_disabled {
52+
#![cfg_attr(test, allow(dead_code))]
53+
use super::*;
54+
55+
pub const LEVEL: Option<c_int> = None;
56+
pub const TYPE: Option<c_int> = None;
57+
pub const SOCKOPT: Option<(c_int, c_int)> = None;
58+
pub const CMSG_SPACE: usize = 0;
59+
60+
pub type Cmsg = c_int;
61+
62+
#[inline]
63+
pub const fn is_match(level: c_int, ty: c_int) -> bool {
64+
let _ = level;
65+
let _ = ty;
66+
false
67+
}
68+
69+
/// # Safety
70+
///
71+
/// * The provided bytes must be aligned to `cmsghdr`
72+
pub unsafe fn decode(bytes: &[u8]) -> Option<(IpV6Address, u32)> {
73+
let _ = bytes;
74+
None
75+
}
76+
77+
#[inline]
78+
pub fn encode(addr: &IpV6Address, local_interface: Option<u32>) -> Cmsg {
79+
let _ = addr;
80+
let _ = local_interface;
81+
unimplemented!("this platform does not support pktinfo")
82+
}
83+
}
84+
85+
mod pktinfo_impl {
86+
#[cfg(not(s2n_quic_platform_pktinfo))]
87+
pub use super::pktinfo_disabled::*;
88+
#[cfg(s2n_quic_platform_pktinfo)]
89+
pub use super::pktinfo_enabled::*;
90+
}
91+
92+
pub use pktinfo_impl::*;
93+
94+
pub const IS_SUPPORTED: bool = cfg!(s2n_quic_platform_pktinfo);
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use super::c_int;
5+
use s2n_quic_core::inet::ExplicitCongestionNotification;
6+
7+
pub const IS_SUPPORTED: bool = super::tos_v4::IS_SUPPORTED || super::tos_v6::IS_SUPPORTED;
8+
9+
#[inline]
10+
pub const fn is_match(level: c_int, ty: c_int) -> bool {
11+
super::tos_v4::is_match(level, ty) || super::tos_v6::is_match(level, ty)
12+
}
13+
14+
#[inline]
15+
pub fn decode(bytes: &[u8]) -> Option<ExplicitCongestionNotification> {
16+
let value = match bytes.len() {
17+
1 => bytes[0],
18+
4 => u32::from_ne_bytes(bytes.try_into().unwrap()) as u8,
19+
_ => return None,
20+
};
21+
22+
Some(ExplicitCongestionNotification::new(value))
23+
}

0 commit comments

Comments
 (0)