netstack3_base/
error.rs

1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Common error types for the netstack.
6
7use net_types::ip::{GenericOverIp, Ip};
8use packet::Nested;
9use thiserror::Error;
10
11/// Error when something is not supported.
12#[derive(Debug, PartialEq, Eq, Error, GenericOverIp)]
13#[generic_over_ip()]
14#[error("not supported")]
15pub struct NotSupportedError;
16
17/// Error when something exists unexpectedly.
18#[derive(Debug, Error, PartialEq, Eq)]
19#[error("already exists")]
20pub struct ExistsError;
21
22impl From<ExistsError> for SocketError {
23    fn from(_: ExistsError) -> SocketError {
24        SocketError::Local(LocalAddressError::AddressInUse)
25    }
26}
27
28/// Error when something unexpectedly doesn't exist, such as trying to
29/// remove an element when the element is not present.
30#[derive(Debug, Error, PartialEq, Eq)]
31#[error("not found")]
32pub struct NotFoundError;
33
34/// Error type for errors common to local addresses.
35#[derive(Error, Debug, PartialEq, GenericOverIp)]
36#[generic_over_ip()]
37pub enum LocalAddressError {
38    /// Cannot bind to address.
39    #[error("can't bind to address")]
40    CannotBindToAddress,
41
42    /// Failed to allocate local port.
43    #[error("failed to allocate local port")]
44    FailedToAllocateLocalPort,
45
46    /// Specified local address does not match any expected address.
47    #[error("specified local address does not match any expected address")]
48    AddressMismatch,
49
50    /// The requested address/socket pair is in use.
51    #[error("address in use")]
52    AddressInUse,
53
54    /// The address cannot be used because of its zone.
55    ///
56    /// TODO(https://fxbug.dev/42054471): Make this an IP socket error once UDP
57    /// sockets contain IP sockets.
58    #[error(transparent)]
59    Zone(#[from] ZonedAddressError),
60
61    /// The requested address is mapped (i.e. an IPv4-mapped-IPv6 address), but
62    /// the socket is not dual-stack enabled.
63    #[error("address is mapped")]
64    AddressUnexpectedlyMapped,
65}
66
67/// Indicates a problem related to an address with a zone.
68#[derive(Copy, Clone, Debug, Error, Eq, PartialEq, GenericOverIp)]
69#[generic_over_ip()]
70pub enum ZonedAddressError {
71    /// The address scope requires a zone but didn't have one.
72    #[error("the address requires a zone but didn't have one")]
73    RequiredZoneNotProvided,
74    /// The address has a zone that doesn't match an existing device constraint.
75    #[error("the socket's device does not match the zone")]
76    DeviceZoneMismatch,
77}
78
79/// An error encountered when attempting to create a UDP, TCP, or ICMP connection.
80#[derive(Error, Debug, PartialEq)]
81pub enum RemoteAddressError {
82    /// No route to host.
83    #[error("no route to host")]
84    NoRoute,
85}
86
87/// Error type for connection errors.
88#[derive(Error, Debug, PartialEq)]
89pub enum SocketError {
90    /// Errors related to the local address.
91    #[error(transparent)]
92    Local(#[from] LocalAddressError),
93
94    /// Errors related to the remote address.
95    #[error(transparent)]
96    Remote(RemoteAddressError),
97}
98
99/// Error when link address resolution failed for a neighbor.
100#[derive(Error, Debug, PartialEq)]
101#[error("address resolution failed")]
102pub struct AddressResolutionFailed;
103
104/// An error and a serializer.
105///
106/// This error type encodes the common pattern of returning an error and the
107/// original serializer that caused the error. For brevity, users are encouraged
108/// to alias this to local types.
109///
110/// It provides a `From` implementation from `(E, S)` for convenience and
111/// impedance matching with the [`packet`] crate.
112#[derive(Debug, PartialEq, Eq)]
113pub struct ErrorAndSerializer<E, S> {
114    /// The error observed.
115    pub error: E,
116    /// The serializer accompanying the error.
117    pub serializer: S,
118}
119
120impl<E, S> ErrorAndSerializer<E, S> {
121    /// Changes the serializer type.
122    pub fn map_serializer<N, F: FnOnce(S) -> N>(self, f: F) -> ErrorAndSerializer<E, N> {
123        let Self { error, serializer } = self;
124        ErrorAndSerializer { error, serializer: f(serializer) }
125    }
126
127    /// Changes the error type.
128    pub fn map_err<N, F: FnOnce(E) -> N>(self, f: F) -> ErrorAndSerializer<N, S> {
129        let Self { error, serializer } = self;
130        ErrorAndSerializer { error: f(error), serializer }
131    }
132
133    /// Changes the error type using [`Into::into`].
134    pub fn err_into<N: From<E>>(self) -> ErrorAndSerializer<N, S> {
135        self.map_err(Into::into)
136    }
137
138    /// Consumes this pair and returns only the error, dropping the serializer.
139    pub fn into_err(self) -> E {
140        self.error
141    }
142}
143
144impl<E, I, O> ErrorAndSerializer<E, Nested<I, O>> {
145    /// A convenience function for dealing with [`Nested`] serializers.
146    ///
147    /// Equivalent to using [`ErrorAndSerializer::map_serializer`].
148    pub fn into_inner(self) -> ErrorAndSerializer<E, I> {
149        self.map_serializer(|s| s.into_inner())
150    }
151}