1
//! Encoding and decoding for relay messages
2
//!
3
//! Relay messages are sent along circuits, inside RELAY or RELAY_EARLY
4
//! cells.
5

            
6
use super::RelayCmd;
7
use crate::chancell::msg::{
8
    DestroyReason, HandshakeType, TAP_C_HANDSHAKE_LEN, TAP_S_HANDSHAKE_LEN,
9
};
10
use crate::chancell::CELL_DATA_LEN;
11
use caret::caret_int;
12
use derive_deftly::Deftly;
13
use std::fmt::Write;
14
use std::net::{IpAddr, Ipv4Addr};
15
use tor_bytes::{EncodeError, EncodeResult, Error, Result};
16
use tor_bytes::{Readable, Reader, Writeable, Writer};
17
use tor_linkspec::EncodedLinkSpec;
18
use tor_llcrypto::pk::rsa::RsaIdentity;
19
use tor_memquota::{derive_deftly_template_HasMemoryCost, memory_cost_structural_copy};
20

            
21
use bitflags::bitflags;
22

            
23
#[cfg(feature = "hs")]
24
#[cfg_attr(docsrs, doc(cfg(feature = "hs")))]
25
pub use super::hs::{
26
    est_intro::EstablishIntro, EstablishRendezvous, IntroEstablished, Introduce1, Introduce2,
27
    IntroduceAck, Rendezvous1, Rendezvous2, RendezvousEstablished,
28
};
29
#[cfg(feature = "experimental-udp")]
30
#[cfg_attr(docsrs, doc(cfg(feature = "experimental-udp")))]
31
pub use super::udp::{ConnectUdp, ConnectedUdp, Datagram};
32

            
33
crate::restrict::restricted_msg! {
34
/// A single parsed relay message, sent or received along a circuit
35
#[derive(Debug, Clone, Deftly)]
36
#[derive_deftly(HasMemoryCost)]
37
#[non_exhaustive]
38
@omit_from "avoid_conflict_with_a_blanket_implementation"
39
pub enum AnyRelayMsg : RelayMsg {
40
    /// Create a stream
41
    Begin,
42
    /// Send data on a stream
43
    Data,
44
    /// Close a stream
45
    End,
46
    /// Successful response to a Begin message
47
    Connected,
48
    /// For flow control
49
    Sendme,
50
    /// Extend a circuit to a new hop (deprecated)
51
    Extend,
52
    /// Successful response to an Extend message (deprecated)
53
    Extended,
54
    /// Extend a circuit to a new hop
55
    Extend2,
56
    /// Successful response to an Extend2 message
57
    Extended2,
58
    /// Partially close a circuit
59
    Truncate,
60
    /// Tell the client that a circuit has been partially closed
61
    Truncated,
62
    /// Used for padding
63
    Drop,
64
    /// Launch a DNS request
65
    Resolve,
66
    /// Response to a Resolve message
67
    Resolved,
68
    /// Start a directory stream
69
    BeginDir,
70
    /// Start a UDP stream.
71
    [feature = "experimental-udp"]
72
    ConnectUdp,
73
    /// Successful response to a ConnectUdp message
74
    [feature = "experimental-udp"]
75
    ConnectedUdp,
76
    /// UDP stream data
77
    [feature = "experimental-udp"]
78
    Datagram,
79
    /// Establish Introduction
80
    [feature = "hs"]
81
    EstablishIntro,
82
    /// Establish Rendezvous
83
    [feature = "hs"]
84
    EstablishRendezvous,
85
    /// Introduce1 (client to introduction point)
86
    [feature = "hs"]
87
    Introduce1,
88
    /// Introduce2 (introduction point to service)
89
    [feature = "hs"]
90
    Introduce2,
91
    /// Rendezvous1 (service to rendezvous point)
92
    [feature = "hs"]
93
    Rendezvous1,
94
    /// Rendezvous2 (rendezvous point to client)
95
    [feature = "hs"]
96
    Rendezvous2,
97
    /// Acknowledgement for EstablishIntro.
98
    [feature = "hs"]
99
    IntroEstablished,
100
    /// Acknowledgment for EstablishRendezvous.
101
    [feature = "hs"]
102
    RendezvousEstablished,
103
    /// Acknowledgement for Introduce1.
104
    [feature = "hs"]
105
    IntroduceAck,
106

            
107
    _ =>
108
    /// An unrecognized command.
109
    Unrecognized,
110
    }
111
}
112

            
113
/// Internal: traits in common different cell bodies.
114
pub trait Body: Sized {
115
    /// Decode a relay cell body from a provided reader.
116
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self>;
117
    /// Encode the body of this cell into the end of a writer.
118
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()>;
119
}
120

            
121
bitflags! {
122
    /// A set of recognized flags that can be attached to a begin cell.
123
    ///
124
    /// For historical reasons, these flags are constructed so that 0
125
    /// is a reasonable default for all of them.
126
    #[derive(Clone, Copy, Debug)]
127
    pub struct BeginFlags : u32 {
128
        /// The client would accept a connection to an IPv6 address.
129
        const IPV6_OKAY = (1<<0);
130
        /// The client would not accept a connection to an IPv4 address.
131
        const IPV4_NOT_OKAY = (1<<1);
132
        /// The client would rather have a connection to an IPv6 address.
133
        const IPV6_PREFERRED = (1<<2);
134
    }
135
}
136
memory_cost_structural_copy!(BeginFlags);
137
impl From<u32> for BeginFlags {
138
2695
    fn from(v: u32) -> Self {
139
2695
        BeginFlags::from_bits_truncate(v)
140
2695
    }
141
}
142

            
143
/// A preference for IPv4 vs IPv6 addresses; usable as a nicer frontend for
144
/// BeginFlags.
145
#[derive(Clone, Default, Copy, Debug, Eq, PartialEq)]
146
#[non_exhaustive]
147
pub enum IpVersionPreference {
148
    /// Only IPv4 is allowed.
149
    Ipv4Only,
150
    /// IPv4 and IPv6 are both allowed, and IPv4 is preferred.
151
    #[default]
152
    Ipv4Preferred,
153
    /// IPv4 and IPv6 are both allowed, and IPv6 is preferred.
154
    Ipv6Preferred,
155
    /// Only IPv6 is allowed.
156
    Ipv6Only,
157
}
158
impl From<IpVersionPreference> for BeginFlags {
159
1176
    fn from(v: IpVersionPreference) -> Self {
160
        use IpVersionPreference::*;
161
1176
        match v {
162
            Ipv4Only => 0.into(),
163
1176
            Ipv4Preferred => BeginFlags::IPV6_OKAY,
164
            Ipv6Preferred => BeginFlags::IPV6_OKAY | BeginFlags::IPV6_PREFERRED,
165
            Ipv6Only => BeginFlags::IPV4_NOT_OKAY,
166
        }
167
1176
    }
168
}
169

            
170
/// A Begin message creates a new data stream.
171
///
172
/// Upon receiving a Begin message, relays should try to open a new stream
173
/// for the client, if their exit policy permits, and associate it with a
174
/// new TCP connection to the target address.
175
///
176
/// If the exit decides to reject the Begin message, or if the TCP
177
/// connection fails, the exit should send an End message.
178
///
179
/// Clients should reject these messages.
180
#[derive(Debug, Clone, Deftly)]
181
#[derive_deftly(HasMemoryCost)]
182
pub struct Begin {
183
    /// Ascii string describing target address
184
    addr: Vec<u8>,
185
    /// Target port
186
    port: u16,
187
    /// Flags that describe how to resolve the address
188
    flags: BeginFlags,
189
}
190

            
191
impl Begin {
192
    /// Construct a new Begin cell
193
84
    pub fn new<F>(addr: &str, port: u16, flags: F) -> crate::Result<Self>
194
84
    where
195
84
        F: Into<BeginFlags>,
196
84
    {
197
84
        if !addr.is_ascii() {
198
2
            return Err(crate::Error::BadStreamAddress);
199
82
        }
200
82
        let mut addr = addr.to_string();
201
82
        addr.make_ascii_lowercase();
202
82
        Ok(Begin {
203
82
            addr: addr.into_bytes(),
204
82
            port,
205
82
            flags: flags.into(),
206
82
        })
207
84
    }
208

            
209
    /// Return the address requested in this message.
210
    pub fn addr(&self) -> &[u8] {
211
        &self.addr[..]
212
    }
213

            
214
    /// Return the port requested by this message.
215
    pub fn port(&self) -> u16 {
216
        self.port
217
    }
218

            
219
    /// Return the set of flags provided in this message.
220
    pub fn flags(&self) -> BeginFlags {
221
        self.flags
222
    }
223
}
224

            
225
impl Body for Begin {
226
2009
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
227
1960
        let addr = {
228
2009
            if r.peek(1)? == b"[" {
229
                // IPv6 address
230
98
                r.advance(1)?;
231
98
                let a = r.take_until(b']')?;
232
98
                let colon = r.take_u8()?;
233
98
                if colon != b':' {
234
49
                    return Err(Error::InvalidMessage("missing port in begin cell".into()));
235
49
                }
236
49
                a
237
            } else {
238
                // IPv4 address, or hostname.
239
1911
                r.take_until(b':')?
240
            }
241
        };
242
1960
        let port = r.take_until(0)?;
243
1960
        let flags = if r.remaining() >= 4 { r.take_u32()? } else { 0 };
244

            
245
1960
        if !addr.is_ascii() {
246
49
            return Err(Error::InvalidMessage(
247
49
                "target address in begin cell not ascii".into(),
248
49
            ));
249
1911
        }
250

            
251
1911
        let port = std::str::from_utf8(port)
252
1911
            .map_err(|_| Error::InvalidMessage("port in begin cell not utf8".into()))?;
253

            
254
1911
        let port = port
255
1911
            .parse()
256
1911
            .map_err(|_| Error::InvalidMessage("port in begin cell not a valid port".into()))?;
257

            
258
1911
        Ok(Begin {
259
1911
            addr: addr.into(),
260
1911
            port,
261
1911
            flags: flags.into(),
262
1911
        })
263
2009
    }
264
88
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
265
88
        if self.addr.contains(&b':') {
266
4
            w.write_u8(b'[');
267
4
            w.write_all(&self.addr[..]);
268
4
            w.write_u8(b']');
269
84
        } else {
270
84
            w.write_all(&self.addr[..]);
271
84
        }
272
88
        w.write_u8(b':');
273
88
        w.write_all(self.port.to_string().as_bytes());
274
88
        w.write_u8(0);
275
88
        if self.flags.bits() != 0 {
276
76
            w.write_u32(self.flags.bits());
277
80
        }
278
88
        Ok(())
279
88
    }
280
}
281

            
282
/// A Data message represents data sent along a stream.
283
///
284
/// Upon receiving a Data message for a live stream, the client or
285
/// exit sends that data onto the associated TCP connection.
286
///
287
/// These messages hold between 1 and [Data::MAXLEN] bytes of data each;
288
/// they are the most numerous messages on the Tor network.
289
#[derive(Debug, Clone, Deftly)]
290
#[derive_deftly(HasMemoryCost)]
291
pub struct Data {
292
    /// Contents of the cell, to be sent on a specific stream
293
    ///
294
    /// INVARIANT: Holds between 1 and [`Data::MAXLEN`] bytes, inclusive.
295
    //
296
    // TODO: There's a good case to be made that this should be a BoxedCellBody
297
    // instead, to avoid allocations and copies.  But first probably we should
298
    // figure out how proposal 340 will work with this.  Possibly, we will wind
299
    // up using `bytes` or something.
300
    body: Vec<u8>,
301
}
302
impl Data {
303
    /// The longest allowable body length for a single data cell.
304
    /// Relay command (1) + 'Recognized' (2) + StreamID (2) + Digest (4) + Length (2) = 11
305
    pub const MAXLEN: usize = CELL_DATA_LEN - 11;
306

            
307
    /// Construct a new data cell.
308
    ///
309
    /// Returns an error if `inp` is longer than [`Data::MAXLEN`] bytes.
310
882
    pub fn new(inp: &[u8]) -> crate::Result<Self> {
311
882
        if inp.len() > Data::MAXLEN {
312
49
            return Err(crate::Error::CantEncode("Data message too long"));
313
833
        }
314
833
        if inp.is_empty() {
315
            return Err(crate::Error::CantEncode("Empty data message"));
316
833
        }
317
833
        Ok(Self::new_unchecked(inp.into()))
318
882
    }
319

            
320
    /// Construct a new data cell, taking as many bytes from `inp`
321
    /// as possible.
322
    ///
323
    /// Return the data cell, and a slice holding any bytes that
324
    /// wouldn't fit (if any).
325
    ///
326
    /// # Panics
327
    ///
328
    /// Panics if `inp` is empty.
329
    #[deprecated(since = "0.16.1", note = "Use try_split_from instead.")]
330
    pub fn split_from(inp: &[u8]) -> (Self, &[u8]) {
331
        Self::try_split_from(inp).expect("Tried to split a Data message from an empty input.")
332
    }
333

            
334
    /// Construct a new data cell, taking as many bytes from `inp`
335
    /// as possible.
336
    ///
337
    /// Return the data cell, and a slice holding any bytes that
338
    /// wouldn't fit (if any).
339
    ///
340
    /// Returns None if the input was empty.
341
70315
    pub fn try_split_from(inp: &[u8]) -> Option<(Self, &[u8])> {
342
70315
        if inp.is_empty() {
343
            return None;
344
70315
        }
345
70315
        let len = std::cmp::min(inp.len(), Data::MAXLEN);
346
70315
        let (data, remainder) = inp.split_at(len);
347
70315
        Some((Self::new_unchecked(data.into()), remainder))
348
70315
    }
349

            
350
    /// Construct a new data cell from a provided vector of bytes.
351
    ///
352
    /// The vector _must_ not have more than [`Data::MAXLEN`] bytes, and must
353
    /// not be empty.
354
71148
    fn new_unchecked(body: Vec<u8>) -> Self {
355
71148
        debug_assert!((1..=Data::MAXLEN).contains(&body.len()));
356
71148
        Data { body }
357
71148
    }
358
}
359
impl From<Data> for Vec<u8> {
360
504
    fn from(data: Data) -> Vec<u8> {
361
504
        data.body
362
504
    }
363
}
364
impl AsRef<[u8]> for Data {
365
63161
    fn as_ref(&self) -> &[u8] {
366
63161
        &self.body[..]
367
63161
    }
368
}
369

            
370
impl Body for Data {
371
64876
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
372
64876
        if r.remaining() == 0 {
373
            return Err(Error::InvalidMessage("Empty DATA message".into()));
374
64876
        }
375
64876
        Ok(Data {
376
64876
            body: r.take(r.remaining())?.into(),
377
        })
378
64876
    }
379
2806
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
380
2806
        w.write_all(&self.body);
381
2806
        Ok(())
382
2806
    }
383
}
384

            
385
/// An End message tells the other end of the circuit to close a stream.
386
///
387
/// Note that End messages do not implement a true half-closed state,
388
/// so after sending an End message each party needs to wait a while
389
/// to be sure that the stream is completely dead.
390
#[derive(Debug, Clone, Deftly)]
391
#[derive_deftly(HasMemoryCost)]
392
pub struct End {
393
    /// Reason for closing the stream
394
    reason: EndReason,
395
    /// If the reason is EXITPOLICY, this holds the resolved address an
396
    /// associated TTL.  The TTL is set to MAX if none was given.
397
    addr: Option<(IpAddr, u32)>,
398
}
399

            
400
caret_int! {
401
    /// A declared reason for closing a stream
402
    #[derive(Deftly)]
403
    #[derive_deftly(HasMemoryCost)]
404
    pub struct EndReason(u8) {
405
        /// Closing a stream because of an unspecified reason.
406
        ///
407
        /// This is the only END reason that clients send.
408
        MISC = 1,
409
        /// Couldn't look up hostname.
410
        RESOLVEFAILED = 2,
411
        /// Remote host refused connection.
412
        CONNECTREFUSED = 3,
413
        /// Closing a stream because of an exit-policy violation.
414
        EXITPOLICY = 4,
415
        /// Circuit destroyed
416
        DESTROY = 5,
417
        /// Anonymized TCP connection was closed
418
        DONE = 6,
419
        /// Connection timed out, or OR timed out while connecting
420
        TIMEOUT = 7,
421
        /// No route to target destination.
422
        NOROUTE = 8,
423
        /// OR is entering hibernation and not handling requests
424
        HIBERNATING = 9,
425
        /// Internal error at the OR
426
        INTERNAL = 10,
427
        /// Ran out of resources to fulfill requests
428
        RESOURCELIMIT = 11,
429
        /// Connection unexpectedly reset
430
        CONNRESET = 12,
431
        /// Tor protocol violation
432
        TORPROTOCOL = 13,
433
        /// BEGIN_DIR cell at a non-directory-cache.
434
        NOTDIRECTORY = 14,
435
    }
436
}
437

            
438
impl tor_error::HasKind for EndReason {
439
    fn kind(&self) -> tor_error::ErrorKind {
440
        use tor_error::ErrorKind as EK;
441
        use EndReason as E;
442
        match *self {
443
            E::MISC => EK::RemoteStreamError,
444
            E::RESOLVEFAILED => EK::RemoteHostResolutionFailed,
445
            E::CONNECTREFUSED => EK::RemoteConnectionRefused,
446
            E::EXITPOLICY => EK::ExitPolicyRejected,
447
            E::DESTROY => EK::CircuitCollapse,
448
            E::DONE => EK::RemoteStreamClosed,
449
            E::TIMEOUT => EK::ExitTimeout,
450
            E::NOROUTE => EK::RemoteNetworkFailed,
451
            E::RESOURCELIMIT | E::HIBERNATING => EK::RelayTooBusy,
452
            E::INTERNAL | E::TORPROTOCOL | E::NOTDIRECTORY => EK::TorProtocolViolation,
453
            E::CONNRESET => EK::RemoteStreamReset,
454
            _ => EK::RemoteStreamError,
455
        }
456
    }
457
}
458

            
459
impl End {
460
    /// Make a new END_REASON_MISC message.
461
    ///
462
    /// Clients send this every time they decide to close a stream.
463
833
    pub fn new_misc() -> Self {
464
833
        End {
465
833
            reason: EndReason::MISC,
466
833
            addr: None,
467
833
        }
468
833
    }
469
    /// Make a new END message with the provided end reason.
470
441
    pub fn new_with_reason(reason: EndReason) -> Self {
471
441
        End { reason, addr: None }
472
441
    }
473
    /// Make a new END message with END_REASON_EXITPOLICY, and the
474
    /// provided address and ttl.
475
147
    pub fn new_exitpolicy(addr: IpAddr, ttl: u32) -> Self {
476
147
        End {
477
147
            reason: EndReason::EXITPOLICY,
478
147
            addr: Some((addr, ttl)),
479
147
        }
480
147
    }
481
    /// Return the provided EndReason for this End cell.
482
196
    pub fn reason(&self) -> EndReason {
483
196
        self.reason
484
196
    }
485
}
486
impl Body for End {
487
882
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
488
882
        if r.remaining() == 0 {
489
49
            return Ok(End {
490
49
                reason: EndReason::MISC,
491
49
                addr: None,
492
49
            });
493
833
        }
494
833
        let reason = r.take_u8()?.into();
495
833
        if reason == EndReason::EXITPOLICY {
496
147
            let addr = match r.remaining() {
497
98
                4 | 8 => IpAddr::V4(r.extract()?),
498
49
                16 | 20 => IpAddr::V6(r.extract()?),
499
                _ => {
500
                    // Ignores other message lengths.
501
                    return Ok(End { reason, addr: None });
502
                }
503
            };
504
147
            let ttl = if r.remaining() == 4 {
505
98
                r.take_u32()?
506
            } else {
507
49
                u32::MAX
508
            };
509
147
            Ok(End {
510
147
                reason,
511
147
                addr: Some((addr, ttl)),
512
147
            })
513
        } else {
514
686
            Ok(End { reason, addr: None })
515
        }
516
882
    }
517
70
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
518
70
        w.write_u8(self.reason.into());
519
70
        if let (EndReason::EXITPOLICY, Some((addr, ttl))) = (self.reason, self.addr) {
520
12
            match addr {
521
8
                IpAddr::V4(v4) => w.write(&v4)?,
522
4
                IpAddr::V6(v6) => w.write(&v6)?,
523
            }
524
12
            w.write_u32(ttl);
525
58
        }
526
70
        Ok(())
527
70
    }
528
}
529

            
530
impl From<EndReason> for std::io::ErrorKind {
531
    fn from(e: EndReason) -> Self {
532
        use std::io::ErrorKind::*;
533
        match e {
534
            EndReason::RESOLVEFAILED => NotFound,
535
            EndReason::CONNECTREFUSED => ConnectionRefused,
536
            EndReason::EXITPOLICY => ConnectionRefused,
537
            EndReason::DESTROY => ConnectionAborted,
538
            EndReason::DONE => UnexpectedEof,
539
            EndReason::TIMEOUT => TimedOut,
540
            EndReason::HIBERNATING => ConnectionRefused,
541
            EndReason::RESOURCELIMIT => ConnectionRefused,
542
            EndReason::CONNRESET => ConnectionReset,
543
            EndReason::TORPROTOCOL => InvalidData,
544
            EndReason::NOTDIRECTORY => ConnectionRefused,
545
            EndReason::INTERNAL | EndReason::NOROUTE | EndReason::MISC => Other,
546
            _ => Other,
547
        }
548
    }
549
}
550

            
551
/// A Connected message is a successful response to a Begin message
552
///
553
/// When an outgoing connection succeeds, the exit sends a Connected
554
/// back to the client.
555
///
556
/// Clients never send Connected messages.
557
#[derive(Debug, Clone, Deftly)]
558
#[derive_deftly(HasMemoryCost)]
559
pub struct Connected {
560
    /// Resolved address and TTL (time to live) in seconds
561
    addr: Option<(IpAddr, u32)>,
562
}
563
impl Connected {
564
    /// Construct a new empty connected cell.
565
980
    pub fn new_empty() -> Self {
566
980
        Connected { addr: None }
567
980
    }
568
    /// Construct a connected cell with an address and a time-to-live value.
569
1078
    pub fn new_with_addr(addr: IpAddr, ttl: u32) -> Self {
570
1078
        Connected {
571
1078
            addr: Some((addr, ttl)),
572
1078
        }
573
1078
    }
574
}
575
impl Body for Connected {
576
1666
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
577
1666
        if r.remaining() == 0 {
578
539
            return Ok(Connected { addr: None });
579
1127
        }
580
1127
        let ipv4 = r.take_u32()?;
581
1127
        let addr = if ipv4 == 0 {
582
98
            if r.take_u8()? != 6 {
583
49
                return Err(Error::InvalidMessage(
584
49
                    "Invalid address type in CONNECTED cell".into(),
585
49
                ));
586
49
            }
587
49
            IpAddr::V6(r.extract()?)
588
        } else {
589
1029
            IpAddr::V4(ipv4.into())
590
        };
591
1078
        let ttl = r.take_u32()?;
592

            
593
1078
        Ok(Connected {
594
1078
            addr: Some((addr, ttl)),
595
1078
        })
596
1666
    }
597
94
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
598
94
        if let Some((addr, ttl)) = self.addr {
599
48
            match addr {
600
44
                IpAddr::V4(v4) => w.write(&v4)?,
601
4
                IpAddr::V6(v6) => {
602
4
                    w.write_u32(0);
603
4
                    w.write_u8(6);
604
4
                    w.write(&v6)?;
605
                }
606
            }
607
48
            w.write_u32(ttl);
608
46
        }
609
94
        Ok(())
610
94
    }
611
}
612

            
613
/// A Sendme message is used to increase flow-control windows.
614
///
615
/// To avoid congestion, each Tor circuit and stream keeps track of a
616
/// number of data cells that it is willing to send.  It decrements
617
/// these numbers every time it sends a cell.  If these numbers reach
618
/// zero, then no more cells can be sent on the stream or circuit.
619
///
620
/// The only way to re-increment these numbers is by receiving a
621
/// Sendme cell from the other end of the circuit or stream.
622
///
623
/// For security, current circuit-level Sendme cells include an
624
/// authentication tag that proves knowledge of the cells that they are
625
/// acking.
626
///
627
/// See [tor-spec.txt](https://spec.torproject.org/tor-spec) for more
628
/// information; also see the source for `tor_proto::circuit::sendme`.
629
#[derive(Debug, Clone, Deftly)]
630
#[derive_deftly(HasMemoryCost)]
631
pub struct Sendme {
632
    /// A tag value authenticating the previously received data.
633
    digest: Option<Vec<u8>>,
634
}
635
impl Sendme {
636
    /// Return a new empty sendme cell
637
    ///
638
    /// This format is used on streams, and on circuits without sendme
639
    /// authentication.
640
196
    pub fn new_empty() -> Self {
641
196
        Sendme { digest: None }
642
196
    }
643
    /// This format is used on circuits with sendme authentication.
644
245
    pub fn new_tag(x: [u8; 20]) -> Self {
645
245
        Sendme {
646
245
            digest: Some(x.into()),
647
245
        }
648
245
    }
649
    /// Consume this cell and return its authentication tag, if any
650
196
    pub fn into_tag(self) -> Option<Vec<u8>> {
651
196
        self.digest
652
196
    }
653
}
654
impl Body for Sendme {
655
490
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
656
490
        let digest = if r.remaining() == 0 {
657
245
            None
658
        } else {
659
245
            let ver = r.take_u8()?;
660
245
            match ver {
661
                0 => None,
662
                1 => {
663
245
                    let dlen = r.take_u16()?;
664
245
                    Some(r.take(dlen as usize)?.into())
665
                }
666
                _ => {
667
                    return Err(Error::InvalidMessage("Unrecognized SENDME version.".into()));
668
                }
669
            }
670
        };
671
490
        Ok(Sendme { digest })
672
490
    }
673
24
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
674
24
        match self.digest {
675
12
            None => (),
676
12
            Some(x) => {
677
12
                w.write_u8(1);
678
12
                let bodylen: u16 = x
679
12
                    .len()
680
12
                    .try_into()
681
12
                    .map_err(|_| EncodeError::BadLengthValue)?;
682
12
                w.write_u16(bodylen);
683
12
                w.write_all(&x);
684
            }
685
        }
686
24
        Ok(())
687
24
    }
688
}
689

            
690
/// Extend was an obsolete circuit extension message format.
691
///
692
/// This format only handled IPv4 addresses, RSA identities, and the
693
/// TAP handshake.  Modern Tor clients use Extend2 instead.
694
#[derive(Debug, Clone, Deftly)]
695
#[derive_deftly(HasMemoryCost)]
696
pub struct Extend {
697
    /// Where to extend to (address)
698
    addr: Ipv4Addr,
699
    /// Where to extend to (port)
700
    port: u16,
701
    /// A TAP handshake to send
702
    handshake: Vec<u8>,
703
    /// The RSA identity of the target relay
704
    rsaid: RsaIdentity,
705
}
706
impl Extend {
707
    /// Construct a new (deprecated) extend cell
708
49
    pub fn new(addr: Ipv4Addr, port: u16, handshake: Vec<u8>, rsaid: RsaIdentity) -> Self {
709
49
        Extend {
710
49
            addr,
711
49
            port,
712
49
            handshake,
713
49
            rsaid,
714
49
        }
715
49
    }
716
}
717
impl Body for Extend {
718
49
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
719
49
        let addr = r.extract()?;
720
49
        let port = r.take_u16()?;
721
49
        let handshake = r.take(TAP_C_HANDSHAKE_LEN)?.into();
722
49
        let rsaid = r.extract()?;
723
49
        Ok(Extend {
724
49
            addr,
725
49
            port,
726
49
            handshake,
727
49
            rsaid,
728
49
        })
729
49
    }
730
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
731
4
        w.write(&self.addr)?;
732
4
        w.write_u16(self.port);
733
4
        w.write_all(&self.handshake[..]);
734
4
        w.write(&self.rsaid)?;
735
4
        Ok(())
736
4
    }
737
}
738

            
739
/// Extended was an obsolete circuit extension message, sent in reply to
740
/// an Extend message.
741
///
742
/// Like Extend, the Extended message was only designed for the TAP
743
/// handshake.
744
#[derive(Debug, Clone, Deftly)]
745
#[derive_deftly(HasMemoryCost)]
746
pub struct Extended {
747
    /// Contents of the handshake sent in response to the EXTEND
748
    handshake: Vec<u8>,
749
}
750
impl Extended {
751
    /// Construct a new Extended message with the provided handshake
752
245
    pub fn new(handshake: Vec<u8>) -> Self {
753
245
        Extended { handshake }
754
245
    }
755
}
756
impl Body for Extended {
757
49
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
758
49
        let handshake = r.take(TAP_S_HANDSHAKE_LEN)?.into();
759
49
        Ok(Extended { handshake })
760
49
    }
761
12
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
762
12
        w.write_all(&self.handshake);
763
12
        Ok(())
764
12
    }
765
}
766

            
767
/// An Extend2 message tells the last relay in a circuit to extend to a new
768
/// hop.
769
///
770
/// When a relay (call it R) receives an Extend2 message, it tries to
771
/// find (or make) a channel to the other relay (R') described in the
772
/// list of link specifiers. (A link specifier can be an IP addresses
773
/// or a cryptographic identity).  Once R has such a channel, the
774
/// it packages the client's handshake data as a new Create2 message
775
/// R'.  If R' replies with a Created2 (success) message, R packages
776
/// that message's contents in an Extended message.
777
//
778
/// Unlike Extend messages, Extend2 messages can encode any handshake
779
/// type, and can describe relays in ways other than IPv4 addresses
780
/// and RSA identities.
781
#[derive(Debug, Clone, Deftly)]
782
#[derive_deftly(HasMemoryCost)]
783
pub struct Extend2 {
784
    /// A vector of "link specifiers"
785
    ///
786
    /// These link specifiers describe where to find the target relay
787
    /// that the recipient should extend to.  They include things like
788
    /// IP addresses and identity keys.
789
    linkspec: Vec<EncodedLinkSpec>,
790
    /// Type of handshake to be sent in a CREATE2 cell
791
    handshake_type: HandshakeType,
792
    /// Body of the handshake to be sent in a CREATE2 cell
793
    handshake: Vec<u8>,
794
}
795
impl Extend2 {
796
    /// Create a new Extend2 cell.
797
1225
    pub fn new(
798
1225
        linkspec: Vec<EncodedLinkSpec>,
799
1225
        handshake_type: HandshakeType,
800
1225
        handshake: Vec<u8>,
801
1225
    ) -> Self {
802
1225
        Extend2 {
803
1225
            linkspec,
804
1225
            handshake_type,
805
1225
            handshake,
806
1225
        }
807
1225
    }
808

            
809
    /// Return the type of this handshake.
810
49
    pub fn handshake_type(&self) -> HandshakeType {
811
49
        self.handshake_type
812
49
    }
813

            
814
    /// Return the inner handshake for this Extend2 cell.
815
441
    pub fn handshake(&self) -> &[u8] {
816
441
        &self.handshake[..]
817
441
    }
818
}
819

            
820
impl Body for Extend2 {
821
490
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
822
490
        let n = r.take_u8()?;
823
490
        let linkspec = r.extract_n(n as usize)?;
824
490
        let handshake_type = r.take_u16()?.into();
825
490
        let hlen = r.take_u16()?;
826
490
        let handshake = r.take(hlen as usize)?.into();
827
490
        Ok(Extend2 {
828
490
            linkspec,
829
490
            handshake_type,
830
490
            handshake,
831
490
        })
832
490
    }
833
52
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
834
52
        let n_linkspecs: u8 = self
835
52
            .linkspec
836
52
            .len()
837
52
            .try_into()
838
52
            .map_err(|_| EncodeError::BadLengthValue)?;
839
52
        w.write_u8(n_linkspecs);
840
156
        for ls in &self.linkspec {
841
104
            w.write(ls)?;
842
        }
843
52
        w.write_u16(self.handshake_type.into());
844
52
        let handshake_len: u16 = self
845
52
            .handshake
846
52
            .len()
847
52
            .try_into()
848
52
            .map_err(|_| EncodeError::BadLengthValue)?;
849
52
        w.write_u16(handshake_len);
850
52
        w.write_all(&self.handshake[..]);
851
52
        Ok(())
852
52
    }
853
}
854

            
855
/// Extended2 is a successful reply to an Extend2 message.
856
///
857
/// Extended2 messages are generated by the former last hop of a
858
/// circuit, to tell the client that they have successfully completed
859
/// a handshake on the client's behalf.
860
#[derive(Debug, Clone, Deftly)]
861
#[derive_deftly(HasMemoryCost)]
862
pub struct Extended2 {
863
    /// Contents of the CREATED2 cell that the new final hop sent in
864
    /// response
865
    handshake: Vec<u8>,
866
}
867
impl Extended2 {
868
    /// Construct a new Extended2 message with the provided handshake
869
882
    pub fn new(handshake: Vec<u8>) -> Self {
870
882
        Extended2 { handshake }
871
882
    }
872
    /// Consume this extended2 cell and return its body.
873
588
    pub fn into_body(self) -> Vec<u8> {
874
588
        self.handshake
875
588
    }
876
}
877
impl Body for Extended2 {
878
637
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
879
637
        let hlen = r.take_u16()?;
880
637
        let handshake = r.take(hlen as usize)?;
881
637
        Ok(Extended2 {
882
637
            handshake: handshake.into(),
883
637
        })
884
637
    }
885
38
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
886
38
        let handshake_len: u16 = self
887
38
            .handshake
888
38
            .len()
889
38
            .try_into()
890
38
            .map_err(|_| EncodeError::BadLengthValue)?;
891
38
        w.write_u16(handshake_len);
892
38
        w.write_all(&self.handshake[..]);
893
38
        Ok(())
894
38
    }
895
}
896

            
897
/// A Truncated message is sent to the client when the remaining hops
898
/// of a circuit have gone away.
899
///
900
/// NOTE: Current Tor implementations often treat Truncated messages and
901
/// Destroy messages interchangeably.  Truncated was intended to be a
902
/// "soft" Destroy, that would leave the unaffected parts of a circuit
903
/// still usable.
904
#[derive(Debug, Clone, Deftly)]
905
#[derive_deftly(HasMemoryCost)]
906
pub struct Truncated {
907
    /// Reason for which this circuit was truncated.
908
    reason: DestroyReason,
909
}
910
impl Truncated {
911
    /// Construct a new truncated message.
912
49
    pub fn new(reason: DestroyReason) -> Self {
913
49
        Truncated { reason }
914
49
    }
915
    /// Get the provided reason to truncate the circuit.
916
    pub fn reason(self) -> DestroyReason {
917
        self.reason
918
    }
919
}
920
impl Body for Truncated {
921
49
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
922
49
        Ok(Truncated {
923
49
            reason: r.take_u8()?.into(),
924
        })
925
49
    }
926
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
927
4
        w.write_u8(self.reason.into());
928
4
        Ok(())
929
4
    }
930
}
931

            
932
/// A Resolve message launches a DNS lookup stream.
933
///
934
/// A client sends a Resolve message when it wants to perform a DNS
935
/// lookup _without_ connecting to the resulting address.  On success
936
/// the exit responds with a Resolved message; on failure it responds
937
/// with an End message.
938
#[derive(Debug, Clone, Deftly)]
939
#[derive_deftly(HasMemoryCost)]
940
pub struct Resolve {
941
    /// Ascii-encoded address to resolve
942
    query: Vec<u8>,
943
}
944
impl Resolve {
945
    /// Construct a new resolve message to look up a hostname.
946
98
    pub fn new(s: &str) -> Self {
947
98
        Resolve {
948
98
            query: s.as_bytes().into(),
949
98
        }
950
98
    }
951
    /// Construct a new resolve message to do a reverse lookup on an address
952
98
    pub fn new_reverse(addr: &IpAddr) -> Self {
953
98
        let query = match addr {
954
49
            IpAddr::V4(v4) => {
955
49
                let [a, b, c, d] = v4.octets();
956
49
                format!("{}.{}.{}.{}.in-addr.arpa", d, c, b, a)
957
            }
958
49
            IpAddr::V6(v6) => {
959
49
                let mut s = String::with_capacity(72);
960
784
                for o in v6.octets().iter().rev() {
961
784
                    let high_nybble = o >> 4;
962
784
                    let low_nybble = o & 15;
963
784
                    write!(s, "{:x}.{:x}.", low_nybble, high_nybble).unwrap();
964
784
                }
965
49
                write!(s, "ip6.arpa").unwrap();
966
49
                s
967
            }
968
        };
969
98
        Resolve {
970
98
            query: query.into_bytes(),
971
98
        }
972
98
    }
973
}
974
impl Body for Resolve {
975
147
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
976
147
        let query = r.take_until(0)?;
977
147
        Ok(Resolve {
978
147
            query: query.into(),
979
147
        })
980
147
    }
981
14
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
982
14
        w.write_all(&self.query[..]);
983
14
        w.write_u8(0);
984
14
        Ok(())
985
14
    }
986
}
987

            
988
/// Possible response to a DNS lookup
989
#[derive(Debug, Clone, Eq, PartialEq, Deftly)]
990
#[derive_deftly(HasMemoryCost)]
991
#[non_exhaustive]
992
pub enum ResolvedVal {
993
    /// We found an IP address
994
    Ip(IpAddr),
995
    /// We found a hostname
996
    Hostname(Vec<u8>),
997
    /// Error; try again
998
    TransientError,
999
    /// Error; don't try again
    NontransientError,
    /// A DNS lookup response that we didn't recognize
    Unrecognized(u8, Vec<u8>),
}
/// Indicates a hostname response
const RES_HOSTNAME: u8 = 0;
/// Indicates an IPv4 response
const RES_IPV4: u8 = 4;
/// Indicates an IPv6 response
const RES_IPV6: u8 = 6;
/// Transient error (okay to try again)
const RES_ERR_TRANSIENT: u8 = 0xF0;
/// Non-transient error (don't try again)
const RES_ERR_NONTRANSIENT: u8 = 0xF1;
impl Readable for ResolvedVal {
441
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
        /// Helper: return the expected length of a resolved answer with
        /// a given type, if there is a particular expected length.
441
        fn res_len(tp: u8) -> Option<usize> {
441
            match tp {
147
                RES_IPV4 => Some(4),
98
                RES_IPV6 => Some(16),
196
                _ => None,
            }
441
        }
441
        let tp = r.take_u8()?;
441
        let len = r.take_u8()? as usize;
441
        if let Some(expected_len) = res_len(tp) {
245
            if len != expected_len {
49
                return Err(Error::InvalidMessage(
49
                    "Wrong length for RESOLVED answer".into(),
49
                ));
196
            }
196
        }
392
        Ok(match tp {
49
            RES_HOSTNAME => Self::Hostname(r.take(len)?.into()),
98
            RES_IPV4 => Self::Ip(IpAddr::V4(r.extract()?)),
98
            RES_IPV6 => Self::Ip(IpAddr::V6(r.extract()?)),
            RES_ERR_TRANSIENT => {
49
                r.advance(len)?;
49
                Self::TransientError
            }
            RES_ERR_NONTRANSIENT => {
49
                r.advance(len)?;
49
                Self::NontransientError
            }
49
            _ => Self::Unrecognized(tp, r.take(len)?.into()),
        })
441
    }
}
impl Writeable for ResolvedVal {
28
    fn write_onto<B: Writer + ?Sized>(&self, w: &mut B) -> EncodeResult<()> {
12
        match self {
4
            Self::Hostname(h) => {
4
                w.write_u8(RES_HOSTNAME);
4
                let h_len: u8 = h
4
                    .len()
4
                    .try_into()
4
                    .map_err(|_| EncodeError::BadLengthValue)?;
4
                w.write_u8(h_len);
4
                w.write_all(&h[..]);
            }
8
            Self::Ip(IpAddr::V4(a)) => {
8
                w.write_u8(RES_IPV4);
8
                w.write_u8(4); // length
8
                w.write(a)?;
            }
4
            Self::Ip(IpAddr::V6(a)) => {
4
                w.write_u8(RES_IPV6);
4
                w.write_u8(16); // length
4
                w.write(a)?;
            }
4
            Self::TransientError => {
4
                w.write_u8(RES_ERR_TRANSIENT);
4
                w.write_u8(0); // length
4
            }
4
            Self::NontransientError => {
4
                w.write_u8(RES_ERR_NONTRANSIENT);
4
                w.write_u8(0); // length
4
            }
4
            Self::Unrecognized(tp, v) => {
4
                w.write_u8(*tp);
4
                let v_len: u8 = v
4
                    .len()
4
                    .try_into()
4
                    .map_err(|_| EncodeError::BadLengthValue)?;
4
                w.write_u8(v_len);
4
                w.write_all(&v[..]);
            }
        }
28
        Ok(())
28
    }
}
/// A Resolved message is a successful reply to a Resolve message.
///
/// The Resolved message contains a list of zero or more addresses,
/// and their associated times-to-live in seconds.
#[derive(Debug, Clone, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Resolved {
    /// List of addresses and their associated time-to-live values.
    answers: Vec<(ResolvedVal, u32)>,
}
impl Resolved {
    /// Return a new empty Resolved object with no answers.
343
    pub fn new_empty() -> Self {
343
        Resolved {
343
            answers: Vec::new(),
343
        }
343
    }
    /// Return a new Resolved object reporting a name lookup error.
    ///
    /// TODO: Is getting no answer an error; or it is represented by
    /// a list of no answers?
98
    pub fn new_err(transient: bool, ttl: u32) -> Self {
98
        let mut res = Self::new_empty();
98
        let err = if transient {
49
            ResolvedVal::TransientError
        } else {
49
            ResolvedVal::NontransientError
        };
98
        res.add_answer(err, ttl);
98
        res
98
    }
    /// Add a single answer to this Resolved message
343
    pub fn add_answer(&mut self, answer: ResolvedVal, ttl: u32) {
343
        self.answers.push((answer, ttl));
343
    }
    /// Consume this Resolved message, returning a vector of the
    /// answers and TTL values that it contains.
    ///
    /// Note that actually relying on these TTL values can be
    /// dangerous in practice, since the relay that sent the cell
    /// could be lying in order to cause more lookups, or to get a
    /// false answer cached for longer.
49
    pub fn into_answers(self) -> Vec<(ResolvedVal, u32)> {
49
        self.answers
49
    }
}
impl Body for Resolved {
441
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
441
        let mut answers = Vec::new();
833
        while r.remaining() > 0 {
441
            let rv = r.extract()?;
392
            let ttl = r.take_u32()?;
392
            answers.push((rv, ttl));
        }
392
        Ok(Resolved { answers })
441
    }
28
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
56
        for (rv, ttl) in &self.answers {
28
            w.write(rv)?;
28
            w.write_u32(*ttl);
        }
28
        Ok(())
28
    }
}
/// A relay message that we didn't recognize
///
/// NOTE: Clients should generally reject these.
#[derive(Debug, Clone, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Unrecognized {
    /// Command that we didn't recognize
    cmd: RelayCmd,
    /// Body associated with that command
    body: Vec<u8>,
}
impl Unrecognized {
    /// Create a new 'unrecognized' cell.
2
    pub fn new<B>(cmd: RelayCmd, body: B) -> Self
2
    where
2
        B: Into<Vec<u8>>,
2
    {
2
        let body = body.into();
2
        Unrecognized { cmd, body }
2
    }
    /// Return the command associated with this message
49
    pub fn cmd(&self) -> RelayCmd {
49
        self.cmd
49
    }
    /// Decode this message, using a provided command.
49
    pub fn decode_with_cmd(cmd: RelayCmd, r: &mut Reader<'_>) -> Result<Self> {
49
        let mut r = Unrecognized::decode_from_reader(r)?;
49
        r.cmd = cmd;
49
        Ok(r)
49
    }
}
impl Body for Unrecognized {
49
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
49
        Ok(Unrecognized {
49
            cmd: 0.into(),
49
            body: r.take(r.remaining())?.into(),
        })
49
    }
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
4
        w.write_all(&self.body[..]);
4
        Ok(())
4
    }
}
/// Declare a message type for a message with an empty body.
macro_rules! empty_body {
   {
       $(#[$meta:meta])*
       pub struct $name:ident {}
   } => {
       $(#[$meta])*
       #[derive(Clone,Debug,Default,derive_deftly::Deftly)]
       #[derive_deftly(tor_memquota::HasMemoryCost)]
       #[non_exhaustive]
       pub struct $name {}
       impl $crate::relaycell::msg::Body for $name {
539
           fn decode_from_reader(_r: &mut Reader<'_>) -> Result<Self> {
539
               Ok(Self::default())
539
           }
30
           fn encode_onto<W: Writer + ?Sized>(self, _w: &mut W) -> EncodeResult<()> {
30
               Ok(())
30
           }
       }
   }
}
pub(crate) use empty_body;
empty_body! {
    /// A padding message, which is always ignored.
    pub struct Drop {}
}
empty_body! {
    /// Tells a circuit to close all downstream hops on the circuit.
    pub struct Truncate {}
}
empty_body! {
    /// Opens a new stream on a directory cache.
    pub struct BeginDir {}
}
/// Helper: declare a RelayMsg implementation for a message type that has a
/// fixed command.
//
// TODO: It might be better to merge Body with RelayMsg, but that is complex,
// since their needs are _slightly_ different.
//
// TODO: If we *do* make the change above, then perhaps we should also implement
// our restricted enums in terms of this, so that there is only one instance of
// [<$body:snake:upper>]
macro_rules! msg_impl_relaymsg {
    ($($body:ident),* $(,)?) =>
    {paste::paste!{
       $(impl crate::relaycell::RelayMsg for $body {
            fn cmd(&self) -> crate::relaycell::RelayCmd { crate::relaycell::RelayCmd::[< $body:snake:upper >] }
            fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()> {
                crate::relaycell::msg::Body::encode_onto(self, w)
            }
1862
            fn decode_from_reader(cmd: RelayCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
1862
                if cmd != crate::relaycell::RelayCmd::[< $body:snake:upper >] {
196
                    return Err(tor_bytes::Error::InvalidMessage(
196
                        format!("Expected {} command; got {cmd}", stringify!([< $body:snake:upper >])).into()
196
                    ));
1666
                }
1666
                crate::relaycell::msg::Body::decode_from_reader(r)
1862
            }
        }
        impl TryFrom<AnyRelayMsg> for $body {
            type Error = crate::Error;
3920
            fn try_from(msg: AnyRelayMsg) -> crate::Result<$body> {
                use crate::relaycell::RelayMsg;
3920
                match msg {
3920
                    AnyRelayMsg::$body(b) => Ok(b),
                    _ => Err(crate::Error::CircProto(format!("Expected {}; got {}" ,
                                                     stringify!([<$body:snake:upper>]),
                                                     msg.cmd())) ),
                }
3920
            }
        }
        )*
    }}
}
msg_impl_relaymsg!(
    Begin, Data, End, Connected, Sendme, Extend, Extended, Extend2, Extended2, Truncate, Truncated,
    Drop, Resolve, Resolved, BeginDir,
);
#[cfg(feature = "experimental-udp")]
msg_impl_relaymsg!(ConnectUdp, ConnectedUdp, Datagram);
#[cfg(feature = "hs")]
msg_impl_relaymsg!(
    EstablishIntro,
    EstablishRendezvous,
    Introduce1,
    Introduce2,
    Rendezvous1,
    Rendezvous2,
    IntroEstablished,
    RendezvousEstablished,
    IntroduceAck,
);