tor_cell/relaycell/
udp.rs

1//! Encoding and decoding for relay messages
2//!
3//! Relay messages are sent along circuits, inside RELAY or RELAY_EARLY
4//! cells.
5
6use super::msg;
7use crate::chancell::CELL_DATA_LEN;
8use derive_deftly::Deftly;
9use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
10use std::str::FromStr;
11use tor_bytes::{EncodeResult, Error, Result};
12use tor_bytes::{Readable, Reader, Writeable, Writer};
13use tor_memquota::derive_deftly_template_HasMemoryCost;
14
15/// Indicates the payload is a hostname.
16const T_HOSTNAME: u8 = 0x01;
17/// Indicates the payload is an IPv4.
18const T_IPV4: u8 = 0x04;
19/// Indicates the payload is an IPv6.
20const T_IPV6: u8 = 0x06;
21
22/// Maximum length of an Address::Hostname set at 255.
23const MAX_HOSTNAME_LEN: usize = u8::MAX as usize;
24
25/// Address contained in a ConnectUdp and ConnectedUdp cell which can
26/// represent a hostname, IPv4 or IPv6 along a port number.
27#[derive(Clone, Debug, Eq, PartialEq, Deftly)]
28#[derive_deftly(HasMemoryCost)]
29pub struct AddressPort {
30    /// Address.
31    addr: Address,
32    /// Port.
33    port: u16,
34}
35
36impl Readable for AddressPort {
37    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
38        Ok(Self {
39            addr: r.extract()?,
40            port: r.take_u16()?,
41        })
42    }
43}
44
45impl Writeable for AddressPort {
46    fn write_onto<B: Writer + ?Sized>(&self, w: &mut B) -> EncodeResult<()> {
47        w.write(&self.addr)?;
48        w.write_u16(self.port);
49        Ok(())
50    }
51}
52
53impl TryFrom<(&str, u16)> for AddressPort {
54    type Error = Error;
55
56    fn try_from(value: (&str, u16)) -> Result<Self> {
57        let addr = Address::from_str(value.0)?;
58        Ok(Self {
59            addr,
60            port: value.1,
61        })
62    }
63}
64
65/// Address representing either a hostname, IPv4 or IPv6.
66#[derive(Clone, Debug, Eq, PartialEq, Deftly)]
67#[derive_deftly(HasMemoryCost)]
68#[non_exhaustive]
69pub enum Address {
70    /// Hostname
71    Hostname(Vec<u8>),
72    /// IP version 4 address
73    Ipv4(Ipv4Addr),
74    /// IP version 6 address
75    Ipv6(Ipv6Addr),
76}
77
78impl Address {
79    /// Return true iff this is a Hostname.
80    pub fn is_hostname(&self) -> bool {
81        matches!(self, Address::Hostname(_))
82    }
83
84    /// Return the cell wire format address type value.
85    fn wire_addr_type(&self) -> u8 {
86        match self {
87            Address::Hostname(_) => T_HOSTNAME,
88            Address::Ipv4(_) => T_IPV4,
89            Address::Ipv6(_) => T_IPV6,
90        }
91    }
92}
93
94impl Readable for Address {
95    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
96        let addr_type = r.take_u8()?;
97        r.read_nested_u8len(|r| {
98            Ok(match addr_type {
99                T_HOSTNAME => {
100                    let h = r.take_rest();
101                    Self::Hostname(h.into())
102                }
103                T_IPV4 => Self::Ipv4(r.extract()?),
104                T_IPV6 => Self::Ipv6(r.extract()?),
105                _ => return Err(Error::InvalidMessage("Invalid address type".into())),
106            })
107        })
108    }
109}
110
111impl Writeable for Address {
112    fn write_onto<B: Writer + ?Sized>(&self, w: &mut B) -> EncodeResult<()> {
113        // Address type.
114        w.write_u8(self.wire_addr_type());
115        // Address length and data.
116        let mut w = w.write_nested_u8len();
117
118        match self {
119            Address::Hostname(h) => {
120                w.write_all(&h[..]);
121            }
122            Address::Ipv4(ip) => w.write(ip)?,
123            Address::Ipv6(ip) => w.write(ip)?,
124        }
125
126        w.finish()
127    }
128}
129
130impl FromStr for Address {
131    type Err = Error;
132
133    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
134        if let Ok(ipv4) = Ipv4Addr::from_str(s) {
135            Ok(Self::Ipv4(ipv4))
136        } else if let Ok(ipv6) = Ipv6Addr::from_str(s) {
137            Ok(Self::Ipv6(ipv6))
138        } else {
139            if s.len() > MAX_HOSTNAME_LEN {
140                return Err(Error::InvalidMessage("Hostname too long".into()));
141            }
142            if s.contains('\0') {
143                return Err(Error::InvalidMessage("Nul byte not permitted".into()));
144            }
145
146            let mut addr = s.to_string();
147            addr.make_ascii_lowercase();
148            Ok(Self::Hostname(addr.into_bytes()))
149        }
150    }
151}
152
153impl From<IpAddr> for Address {
154    fn from(ip: IpAddr) -> Self {
155        match ip {
156            IpAddr::V4(ip) => Address::Ipv4(ip),
157            IpAddr::V6(ip) => Address::Ipv6(ip),
158        }
159    }
160}
161
162/// A ConnectUdp message creates a new UDP data stream.
163///
164/// Upon receiving a ConnectUdp message, a relay tries to connect to the given address with the UDP
165/// protocol if the exit policy permits.
166///
167/// If the exit decides to reject the message, or if the UDP connection fails, the exit should send
168/// an End message.
169///
170/// Clients should reject these messages.
171#[derive(Debug, Clone, Deftly)]
172#[derive_deftly(HasMemoryCost)]
173pub struct ConnectUdp {
174    /// Same as Begin flags.
175    flags: msg::BeginFlags,
176    /// Address to connect to. Can be Hostname, IPv4 or IPv6.
177    addr: AddressPort,
178}
179
180impl ConnectUdp {
181    /// Construct a new ConnectUdp cell
182    pub fn new<F>(addr: &str, port: u16, flags: F) -> crate::Result<Self>
183    where
184        F: Into<msg::BeginFlags>,
185    {
186        Ok(Self {
187            addr: (addr, port)
188                .try_into()
189                .map_err(|_| crate::Error::BadStreamAddress)?,
190            flags: flags.into(),
191        })
192    }
193}
194
195impl msg::Body for ConnectUdp {
196    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
197        let flags = r.take_u32()?;
198        let addr = r.extract()?;
199
200        Ok(Self {
201            flags: flags.into(),
202            addr,
203        })
204    }
205
206    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
207        w.write_u32(self.flags.bits());
208        w.write(&self.addr)?;
209        Ok(())
210    }
211}
212
213/// A ConnectedUdp cell sent in response to a ConnectUdp.
214#[derive(Debug, Clone, Deftly)]
215#[derive_deftly(HasMemoryCost)]
216pub struct ConnectedUdp {
217    /// The address that the relay has bound locally of a ConnectUdp. Note
218    /// that this might not be the relay address from the descriptor.
219    our_address: AddressPort,
220    /// The address that the stream is connected to.
221    their_address: AddressPort,
222}
223
224impl ConnectedUdp {
225    /// Construct a new ConnectedUdp cell.
226    pub fn new(our_address: AddressPort, their_address: AddressPort) -> Result<Self> {
227        Ok(Self {
228            our_address,
229            their_address,
230        })
231    }
232}
233
234impl msg::Body for ConnectedUdp {
235    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
236        let our_address: AddressPort = r.extract()?;
237        if our_address.addr.is_hostname() {
238            return Err(Error::InvalidMessage("Our address is a Hostname".into()));
239        }
240        let their_address: AddressPort = r.extract()?;
241        if their_address.addr.is_hostname() {
242            return Err(Error::InvalidMessage("Their address is a Hostname".into()));
243        }
244
245        Ok(Self {
246            our_address,
247            their_address,
248        })
249    }
250
251    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
252        w.write(&self.our_address)?;
253        w.write(&self.their_address)?;
254        Ok(())
255    }
256}
257
258/// A Datagram message represents data sent along a UDP stream.
259///
260/// Upon receiving a Datagram message for a live stream, the client or
261/// exit sends that data onto the associated UDP connection.
262///
263/// These messages hold between 1 and [Datagram::MAXLEN] bytes of data each.
264#[derive(Debug, Clone, Deftly)]
265#[derive_deftly(HasMemoryCost)]
266pub struct Datagram {
267    /// Contents of the cell, to be sent on a specific stream
268    body: Vec<u8>,
269}
270
271impl Datagram {
272    /// NOTE: Proposal 340, fragmented relay message, might change this value reality.
273    /// The longest allowable body length for a single data cell.
274    //
275    // TODO: This length is incorrect for the RelayCellFormat::V1 cell format.
276    // If/when we return to developing UDP support, we might want to take an approach similar
277    // to that used in Data cells.
278    // Alternatively, we might want to remove the maximum entirely
279    // (if we have implemented prop340 message fragmentation),
280    // or make this message type only usable along with the V1 format.
281    pub const MAXLEN: usize = CELL_DATA_LEN - 11;
282
283    /// Construct a new data cell.
284    ///
285    /// Returns an error if `inp` is longer than [`Datagram::MAXLEN`] bytes.
286    pub fn new(inp: &[u8]) -> crate::Result<Self> {
287        if inp.len() > msg::Data::MAXLEN_V0 {
288            return Err(crate::Error::CantEncode("Datagram too long"));
289        }
290        Ok(Self::new_unchecked(inp.into()))
291    }
292
293    /// Construct a new cell from a provided vector of bytes.
294    ///
295    /// The vector _must_ have fewer than [`Datagram::MAXLEN`] bytes.
296    fn new_unchecked(body: Vec<u8>) -> Self {
297        Self { body }
298    }
299}
300
301impl From<Datagram> for Vec<u8> {
302    fn from(data: Datagram) -> Vec<u8> {
303        data.body
304    }
305}
306
307impl AsRef<[u8]> for Datagram {
308    fn as_ref(&self) -> &[u8] {
309        &self.body[..]
310    }
311}
312
313impl msg::Body for Datagram {
314    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
315        Ok(Datagram {
316            body: r.take(r.remaining())?.into(),
317        })
318    }
319
320    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
321        w.write_all(&self.body);
322        Ok(())
323    }
324}