1use core::convert::Infallible as Never;
6use core::fmt::Debug;
7use core::num::NonZeroU32;
8
9use net_types::ip::{GenericOverIp, Ip, Ipv4, Ipv4Addr, Ipv6, Ipv6SourceAddr, Mtu};
10use packet_formats::icmp::{
11 IcmpDestUnreachable, Icmpv4DestUnreachableCode, Icmpv4ParameterProblemCode, Icmpv4RedirectCode,
12 Icmpv4TimeExceededCode, Icmpv6DestUnreachableCode, Icmpv6ParameterProblemCode,
13 Icmpv6TimeExceededCode,
14};
15use packet_formats::ip::IpProtoExt;
16use strum::{EnumCount as _, IntoEnumIterator as _};
17use strum_macros::{EnumCount, EnumIter};
18
19pub trait BroadcastIpExt: Ip {
21 type BroadcastMarker: Debug + Copy + Clone + PartialEq + Eq + Send + Sync + 'static;
24}
25
26impl BroadcastIpExt for Ipv4 {
27 type BroadcastMarker = ();
28}
29
30impl BroadcastIpExt for Ipv6 {
31 type BroadcastMarker = Never;
32}
33
34#[derive(GenericOverIp)]
37#[generic_over_ip(I, Ip)]
38pub struct WrapBroadcastMarker<I: BroadcastIpExt>(pub I::BroadcastMarker);
39
40#[derive(Clone, Copy, Debug, PartialEq, Eq)]
44pub struct Mms(NonZeroU32);
45
46impl Mms {
47 pub fn from_mtu<I: IpExt>(mtu: Mtu, options_size: u32) -> Option<Self> {
49 NonZeroU32::new(mtu.get().saturating_sub(I::IP_HEADER_LENGTH.get() + options_size))
50 .map(|mms| Self(mms.min(I::IP_MAX_PAYLOAD_LENGTH)))
51 }
52
53 pub fn get(&self) -> NonZeroU32 {
55 let Self(mms) = *self;
56 mms
57 }
58}
59
60#[derive(Copy, Clone, Debug, PartialEq)]
65#[allow(missing_docs)]
66pub enum Icmpv4ErrorCode {
67 DestUnreachable(Icmpv4DestUnreachableCode, IcmpDestUnreachable),
68 Redirect(Icmpv4RedirectCode),
69 TimeExceeded(Icmpv4TimeExceededCode),
70 ParameterProblem(Icmpv4ParameterProblemCode),
71}
72
73impl<I: IcmpIpExt> GenericOverIp<I> for Icmpv4ErrorCode {
74 type Type = I::ErrorCode;
75}
76
77#[derive(Copy, Clone, Debug, PartialEq)]
82#[allow(missing_docs)]
83pub enum Icmpv6ErrorCode {
84 DestUnreachable(Icmpv6DestUnreachableCode),
85 PacketTooBig(Mtu),
86 TimeExceeded(Icmpv6TimeExceededCode),
87 ParameterProblem(Icmpv6ParameterProblemCode),
88}
89
90impl<I: IcmpIpExt> GenericOverIp<I> for Icmpv6ErrorCode {
91 type Type = I::ErrorCode;
92}
93
94#[derive(Debug, Clone, Copy)]
96pub enum IcmpErrorCode {
97 V4(Icmpv4ErrorCode),
99 V6(Icmpv6ErrorCode),
101}
102
103impl From<Icmpv4ErrorCode> for IcmpErrorCode {
104 fn from(v4_err: Icmpv4ErrorCode) -> Self {
105 IcmpErrorCode::V4(v4_err)
106 }
107}
108
109impl From<Icmpv6ErrorCode> for IcmpErrorCode {
110 fn from(v6_err: Icmpv6ErrorCode) -> Self {
111 IcmpErrorCode::V6(v6_err)
112 }
113}
114
115pub trait IcmpIpExt: packet_formats::ip::IpExt + packet_formats::icmp::IcmpIpExt {
117 type ErrorCode: Debug
120 + Copy
121 + PartialEq
122 + GenericOverIp<Self, Type = Self::ErrorCode>
123 + GenericOverIp<Ipv4, Type = Icmpv4ErrorCode>
124 + GenericOverIp<Ipv6, Type = Icmpv6ErrorCode>
125 + Into<IcmpErrorCode>;
126}
127
128impl IcmpIpExt for Ipv4 {
129 type ErrorCode = Icmpv4ErrorCode;
130}
131
132impl IcmpIpExt for Ipv6 {
133 type ErrorCode = Icmpv6ErrorCode;
134}
135
136pub trait IpTypesIpExt: packet_formats::ip::IpExt {
138 type BroadcastMarker: Debug + Copy + Clone + PartialEq + Eq;
141}
142
143impl IpTypesIpExt for Ipv4 {
144 type BroadcastMarker = ();
145}
146
147impl IpTypesIpExt for Ipv6 {
148 type BroadcastMarker = Never;
149}
150
151pub trait IpExt: packet_formats::ip::IpExt + IcmpIpExt + BroadcastIpExt + IpProtoExt {
153 type RecvSrcAddr: Into<Self::Addr> + TryFrom<Self::Addr, Error: Debug> + Copy + Clone;
158 const IP_HEADER_LENGTH: NonZeroU32;
160 const IP_MAX_PAYLOAD_LENGTH: NonZeroU32;
162}
163
164impl IpExt for Ipv4 {
165 type RecvSrcAddr = Ipv4Addr;
166 const IP_HEADER_LENGTH: NonZeroU32 =
167 NonZeroU32::new(packet_formats::ipv4::HDR_PREFIX_LEN as u32).unwrap();
168 const IP_MAX_PAYLOAD_LENGTH: NonZeroU32 =
169 NonZeroU32::new(u16::MAX as u32 - Self::IP_HEADER_LENGTH.get()).unwrap();
170}
171
172impl IpExt for Ipv6 {
173 type RecvSrcAddr = Ipv6SourceAddr;
174 const IP_HEADER_LENGTH: NonZeroU32 =
175 NonZeroU32::new(packet_formats::ipv6::IPV6_FIXED_HDR_LEN as u32).unwrap();
176 const IP_MAX_PAYLOAD_LENGTH: NonZeroU32 = NonZeroU32::new(u16::MAX as u32).unwrap();
177}
178
179#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
184pub struct Mark(pub Option<u32>);
185
186impl From<Option<u32>> for Mark {
187 fn from(m: Option<u32>) -> Self {
188 Self(m)
189 }
190}
191
192#[derive(Debug, Clone, Copy, PartialEq, Eq, EnumCount, EnumIter)]
194pub enum MarkDomain {
195 Mark1,
197 Mark2,
199}
200
201const MARK_DOMAINS: usize = MarkDomain::COUNT;
202
203#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
205pub struct MarkStorage<T>([T; MARK_DOMAINS]);
206
207impl<T> MarkStorage<T> {
208 pub fn new<U, IntoIter>(iter: IntoIter) -> Self
215 where
216 IntoIter: IntoIterator<Item = (MarkDomain, U)>,
217 T: From<Option<U>> + Copy,
218 {
219 let mut storage = MarkStorage([None.into(); MARK_DOMAINS]);
220 for (domain, value) in iter.into_iter() {
221 *storage.get_mut(domain) = Some(value).into();
222 }
223 storage
224 }
225
226 fn domain_as_index(domain: MarkDomain) -> usize {
227 match domain {
228 MarkDomain::Mark1 => 0,
229 MarkDomain::Mark2 => 1,
230 }
231 }
232
233 pub fn get(&self, domain: MarkDomain) -> &T {
235 let Self(inner) = self;
236 &inner[Self::domain_as_index(domain)]
237 }
238
239 pub fn get_mut(&mut self, domain: MarkDomain) -> &mut T {
241 let Self(inner) = self;
242 &mut inner[Self::domain_as_index(domain)]
243 }
244
245 pub fn iter(&self) -> impl Iterator<Item = (MarkDomain, &T)> {
247 let Self(inner) = self;
248 MarkDomain::iter().map(move |domain| (domain, &inner[Self::domain_as_index(domain)]))
249 }
250
251 pub fn zip_with<'a, U>(
253 &'a self,
254 MarkStorage(other): &'a MarkStorage<U>,
255 ) -> impl Iterator<Item = (MarkDomain, &'a T, &'a U)> + 'a {
256 let Self(this) = self;
257 MarkDomain::iter().zip(this.iter().zip(other.iter())).map(|(d, (t, u))| (d, t, u))
258 }
259}
260
261pub type Marks = MarkStorage<Mark>;
263
264impl Marks {
265 pub const UNMARKED: Self = MarkStorage([Mark(None), Mark(None)]);
267}