1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Custom error types for the netstack.
use net_types::ip::{GenericOverIp, Ip};
use packet_formats::error::*;
use thiserror::Error;
/// Results returned from many functions in the netstack.
pub type Result<T> = core::result::Result<T, NetstackError>;
/// Top-level error type the netstack.
#[derive(Error, Debug, PartialEq)]
pub enum NetstackError {
#[error("{}", _0)]
/// Errors related to packet parsing.
Parse(ParseError),
/// Error when item already exists.
#[error("Item already exists")]
Exists,
/// Error when item is not found.
#[error("Item not found")]
NotFound,
/// Errors related to sending UDP frames/packets.
#[error("{}", _0)]
SendUdp(crate::transport::udp::SendToError),
/// Errors related to connections.
#[error("{}", _0)]
Connect(SocketError),
/// Error when there is no route to an address.
#[error("No route to address")]
NoRoute,
/// Error when a maximum transmission unit (MTU) is exceeded.
#[error("MTU exceeded")]
Mtu,
// Add error types here as we add more to the stack.
}
/// Error when something is not supported.
#[derive(Debug, PartialEq, Eq, Error)]
#[error("Not supported")]
pub struct NotSupportedError;
/// Error when something exists unexpectedly.
#[derive(Debug, Error, PartialEq, Eq)]
#[error("Already exists")]
pub struct ExistsError;
impl From<ExistsError> for NetstackError {
fn from(_: ExistsError) -> NetstackError {
NetstackError::Exists
}
}
impl From<ExistsError> for SocketError {
fn from(_: ExistsError) -> SocketError {
SocketError::Local(LocalAddressError::AddressInUse)
}
}
/// Error when something unexpectedly doesn't exist, such as trying to
/// remove an element when the element is not present.
#[derive(Debug, Error, PartialEq, Eq)]
#[error("Not found")]
pub struct NotFoundError;
impl From<NotFoundError> for NetstackError {
fn from(_: NotFoundError) -> NetstackError {
NetstackError::NotFound
}
}
/// Error type for errors common to local addresses.
#[derive(Error, Debug, PartialEq, GenericOverIp)]
#[generic_over_ip()]
pub enum LocalAddressError {
/// Cannot bind to address.
#[error("can't bind to address")]
CannotBindToAddress,
/// Failed to allocate local port.
#[error("failed to allocate local port")]
FailedToAllocateLocalPort,
/// Specified local address does not match any expected address.
#[error("specified local address does not match any expected address")]
AddressMismatch,
/// The requested address/socket pair is in use.
#[error("Address in use")]
AddressInUse,
/// The address cannot be used because of its zone.
///
/// TODO(https://fxbug.dev/103426): Make this an IP socket error once UDP
/// sockets contain IP sockets.
#[error("{}", _0)]
Zone(#[from] ZonedAddressError),
/// The requested address is mapped (i.e. an IPv4-mapped-IPv6 address), but
/// the socket is not dual-stack enabled.
#[error("Address is mapped")]
AddressUnexpectedlyMapped,
}
/// Indicates a problem related to an address with a zone.
#[derive(Copy, Clone, Debug, Error, Eq, PartialEq, GenericOverIp)]
#[generic_over_ip()]
pub enum ZonedAddressError {
/// The address scope requires a zone but didn't have one.
#[error("the address requires a zone but didn't have one")]
RequiredZoneNotProvided,
/// The address has a zone that doesn't match an existing device constraint.
#[error("the socket's device does not match the zone")]
DeviceZoneMismatch,
}
// TODO(joshlf): Once we support a more general model of sockets in which UDP
// and ICMP connections are special cases of UDP and ICMP sockets, we can
// introduce a more specialized ListenerError which does not contain the NoRoute
// variant.
/// An error encountered when attempting to create a UDP, TCP, or ICMP connection.
#[derive(Error, Debug, PartialEq)]
pub enum RemoteAddressError {
/// No route to host.
#[error("no route to host")]
NoRoute,
}
/// Error type for connection errors.
#[derive(Error, Debug, PartialEq)]
pub enum SocketError {
#[error("{}", _0)]
/// Errors related to the local address.
Local(#[from] LocalAddressError),
#[error("{}", _0)]
/// Errors related to the remote address.
Remote(RemoteAddressError),
}
/// Error when no route exists to a remote address.
#[derive(Debug, PartialEq, Eq)]
pub struct NoRouteError;
impl From<NoRouteError> for NetstackError {
fn from(_: NoRouteError) -> NetstackError {
NetstackError::NoRoute
}
}
impl From<NoRouteError> for SocketError {
fn from(_: NoRouteError) -> SocketError {
SocketError::Remote(RemoteAddressError::NoRoute)
}
}
/// Error type for setting properties on IP addresses.
#[derive(Error, Debug, PartialEq)]
pub enum SetIpAddressPropertiesError {
/// The address we tried to set properties on was not found.
#[error("{0}")]
NotFound(#[from] NotFoundError),
/// We tried to set properties on a non-manually-configured address.
#[error("tried to set properties on a non-manually-configured address")]
NotManual,
}
/// Error when link address resolution failed for a neighbor.
#[derive(Debug, PartialEq)]
pub struct AddressResolutionFailed;
/// Error when a static neighbor entry cannot be inserted.
#[derive(Debug, PartialEq, Eq, Error)]
pub enum StaticNeighborInsertionError {
/// The address used for a static neighbor entry is not unicast.
#[error("Address is not unicast")]
AddressNotUnicast,
/// Loopback devices do not support neighbor entries.
#[error("{0}")]
NotSupported(#[from] NotSupportedError),
}