1
//! Different kinds of messages that can be encoded in channel cells.
2

            
3
use super::{BoxedCellBody, CELL_DATA_LEN, ChanCmd, RawCellBody};
4
use std::net::{IpAddr, Ipv4Addr};
5

            
6
use tor_basic_utils::skip_fmt;
7
use tor_bytes::{self, EncodeError, EncodeResult, Error, Readable, Reader, Result, Writer};
8
use tor_memquota::derive_deftly_template_HasMemoryCost;
9
use tor_units::IntegerMilliseconds;
10

            
11
use caret::caret_int;
12
use derive_deftly::Deftly;
13
use educe::Educe;
14

            
15
/// Trait for the 'bodies' of channel messages.
16
pub trait Body: Readable {
17
    /// Decode a channel cell body from a provided reader.
18
7192
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
19
7192
        r.extract()
20
7192
    }
21
    /// Consume this message and encode its body onto `w`.
22
    ///
23
    /// Does not encode anything _but_ the cell body, and does not pad
24
    /// to the cell length.
25
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()>;
26
}
27

            
28
crate::restrict::restricted_msg! {
29
/// Decoded message from a channel.
30
///
31
/// A ChanMsg is an item received on a channel -- a message from
32
/// another Tor client or relay that we are connected to directly over
33
/// a TLS connection.
34
#[derive(Clone, Debug, Deftly)]
35
#[derive_deftly(HasMemoryCost)]
36
#[non_exhaustive]
37
@omit_from "avoid_conflict_with_a_blanket_implementation"
38
pub enum AnyChanMsg : ChanMsg {
39
    /// A Padding message
40
    Padding,
41
    /// Variable-length padding message
42
    Vpadding,
43
    /// (Deprecated) TAP-based cell to create a new circuit.
44
    Create,
45
    /// (Mostly deprecated) HMAC-based cell to create a new circuit.
46
    CreateFast,
47
    /// Cell to create a new circuit
48
    Create2,
49
    /// (Deprecated) Answer to a Create cell
50
    Created,
51
    /// (Mostly Deprecated) Answer to a CreateFast cell
52
    CreatedFast,
53
    /// Answer to a Create2 cell
54
    Created2,
55
    /// A message sent along a circuit, likely to a more-distant relay.
56
    Relay,
57
    /// A message sent along a circuit (limited supply)
58
    RelayEarly,
59
    /// Tear down a circuit
60
    Destroy,
61
    /// Part of channel negotiation: describes our position on the network
62
    Netinfo,
63
    /// Part of channel negotiation: describes what link protocol versions
64
    /// we support
65
    Versions,
66
    /// Negotiates what kind of channel padding to send
67
    PaddingNegotiate,
68
    /// Part of channel negotiation: additional certificates not in the
69
    /// TLS handshake
70
    Certs,
71
    /// Part of channel negotiation: additional random material to be used
72
    /// as part of authentication
73
    AuthChallenge,
74
    /// Part of channel negotiation: used to authenticate relays when they
75
    /// initiate the channel.
76
    Authenticate,
77
    _ =>
78
    /// Any cell whose command we don't recognize
79
    Unrecognized,
80
}
81
}
82

            
83
/// A Padding message is a fixed-length message on a channel that is
84
/// ignored.
85
///
86
/// Padding message can be used to disguise the true amount of data on a
87
/// channel, or as a "keep-alive".
88
///
89
/// The correct response to a padding cell is to drop it and do nothing.
90
#[derive(Clone, Debug, Default, Deftly)]
91
#[derive_deftly(HasMemoryCost)]
92
#[non_exhaustive]
93
pub struct Padding {}
94
impl Padding {
95
    /// Create a new fixed-length padding cell
96
310
    pub fn new() -> Self {
97
310
        Padding {}
98
310
    }
99
}
100
impl Body for Padding {
101
8
    fn encode_onto<W: Writer + ?Sized>(self, _w: &mut W) -> EncodeResult<()> {
102
8
        Ok(())
103
8
    }
104
}
105
impl Readable for Padding {
106
186
    fn take_from(_b: &mut Reader<'_>) -> Result<Self> {
107
186
        Ok(Padding {})
108
186
    }
109
}
110

            
111
/// A VPadding message is a variable-length padding message.
112
///
113
/// The correct response to a padding cell is to drop it and do nothing.
114
#[derive(Clone, Debug, Deftly)]
115
#[derive_deftly(HasMemoryCost)]
116
pub struct Vpadding {
117
    /// How much padding to send in this cell's body.
118
    len: u16,
119
}
120
impl Vpadding {
121
    /// Return a new vpadding cell with given length.
122
124
    pub fn new(len: u16) -> Self {
123
124
        Vpadding { len }
124
124
    }
125
}
126
impl Body for Vpadding {
127
8
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
128
8
        w.write_zeros(self.len as usize);
129
8
        Ok(())
130
8
    }
131
}
132
impl Readable for Vpadding {
133
620
    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
134
620
        if b.remaining() > u16::MAX as usize {
135
            return Err(Error::InvalidMessage(
136
                "Too many bytes in VPADDING cell".into(),
137
            ));
138
620
        }
139
620
        Ok(Vpadding {
140
620
            len: b.remaining() as u16,
141
620
        })
142
620
    }
143
}
144

            
145
/// helper -- declare a fixed-width cell for handshake commands, in which
146
/// a fixed number of bytes matter and the rest are ignored
147
macro_rules! fixed_len_handshake {
148
    {
149
        $(#[$meta:meta])*
150
        $name:ident , $cmd:ident, $len:ident
151
    } => {
152
        $(#[$meta])*
153
        #[derive(Clone,Debug,Deftly)]
154
        #[derive_deftly(HasMemoryCost)]
155
        pub struct $name {
156
            handshake: Vec<u8>
157
        }
158
        impl $name {
159
            /// Create a new cell from a provided handshake.
160
44
            pub fn new<B>(handshake: B) -> Self
161
44
                where B: Into<Vec<u8>>
162
            {
163
44
                let handshake = handshake.into();
164
44
                $name { handshake }
165
44
            }
166
        }
167
        impl Body for $name {
168
16
            fn encode_onto<W: Writer + ?Sized>(self, w: &mut W)  -> EncodeResult<()> {
169
16
                w.write_all(&self.handshake[..]);
170
16
                Ok(())
171
16
            }
172
        }
173
        impl Readable for $name {
174
248
            fn take_from(b: &mut Reader<'_>) -> Result<Self> {
175
                Ok($name {
176
248
                    handshake: b.take($len)?.into(),
177
                })
178
248
            }
179
        }
180
    }
181
}
182

            
183
/// Number of bytes used for a TAP handshake by the initiator.
184
pub(crate) const TAP_C_HANDSHAKE_LEN: usize = 128 + 16 + 42;
185
/// Number of bytes used for a TAP handshake response
186
pub(crate) const TAP_S_HANDSHAKE_LEN: usize = 128 + 20;
187

            
188
/// Number of bytes used for a CREATE_FAST handshake by the initiator
189
const FAST_C_HANDSHAKE_LEN: usize = 20;
190
/// Number of bytes used for a CREATE_FAST handshake response
191
const FAST_S_HANDSHAKE_LEN: usize = 20 + 20;
192

            
193
fixed_len_handshake! {
194
    /// A Create message creates a circuit, using the TAP handshake.
195
    ///
196
    /// TAP is an obsolete handshake based on RSA-1024 and DH-1024.
197
    /// Relays respond to Create message with a Created reply on
198
    /// success, or a Destroy message on failure.
199
    ///
200
    /// In Tor today, Create is only used for the deprecated v2 onion
201
    /// service protocol.
202
    Create, CREATE, TAP_C_HANDSHAKE_LEN
203
}
204
fixed_len_handshake! {
205
    /// A Created message responds to a Created message, using the TAP
206
    /// handshake.
207
    ///
208
    /// TAP is an obsolete handshake based on RSA-1024 and DH-1024.
209
    Created, CREATED, TAP_S_HANDSHAKE_LEN
210
}
211
fixed_len_handshake! {
212
    /// A CreateFast message creates a circuit using no public-key crypto.
213
    ///
214
    /// CreateFast is safe only when used on an already-secure TLS
215
    /// connection.  It can only be used for the first hop of a circuit.
216
    ///
217
    /// Relays reply to a CreateFast message with CreatedFast on
218
    /// success, or a Destroy message on failure.
219
    ///
220
    /// This handshake was originally used for the first hop of every
221
    /// circuit.  Nowadays it is used for creating one-hop circuits
222
    /// when we don't know any onion key for the first hop.
223
    CreateFast, CREATE_FAST, FAST_C_HANDSHAKE_LEN
224
}
225
impl CreateFast {
226
    /// Return the content of this handshake
227
434
    pub fn handshake(&self) -> &[u8] {
228
434
        &self.handshake
229
434
    }
230
}
231
fixed_len_handshake! {
232
    /// A CreatedFast message responds to a CreateFast message
233
    ///
234
    /// Relays send this message back to indicate that the CrateFast handshake
235
    /// is complete.
236
    CreatedFast, CREATED_FAST, FAST_S_HANDSHAKE_LEN
237
}
238
impl CreatedFast {
239
    /// Consume this message and return the content of this handshake
240
434
    pub fn into_handshake(self) -> Vec<u8> {
241
434
        self.handshake
242
434
    }
243
}
244

            
245
caret_int! {
246
    /// Handshake type, corresponding to [`HTYPE` in
247
    /// tor-spec](https://spec.torproject.org/tor-spec/create-created-cells.html).
248
    #[derive(Deftly)]
249
    #[derive_deftly(HasMemoryCost)]
250
    pub struct HandshakeType(u16) {
251
        /// [TAP](https://spec.torproject.org/tor-spec/create-created-cells.html#TAP) -- the original Tor handshake.
252
        TAP = 0,
253

            
254
        // 1 is reserved
255

            
256
        /// [ntor](https://spec.torproject.org/tor-spec/create-created-cells.html#ntor) -- the ntor+curve25519+sha256 handshake.
257
        NTOR = 2,
258
        /// [ntor-v3](https://spec.torproject.org/tor-spec/create-created-cells.html#ntor-v3) -- ntor extended with extra data.
259
        NTOR_V3 = 3,
260
    }
261
}
262

            
263
/// A Create2 message create a circuit on the current channel.
264
///
265
/// To create a circuit, the client sends a Create2 cell containing a
266
/// handshake of a given type; the relay responds with a Created2 cell
267
/// containing a reply.
268
///
269
/// Currently, most Create2 cells contain a client-side instance of the
270
/// "ntor" handshake.
271
#[derive(Clone, Debug, Deftly)]
272
#[derive_deftly(HasMemoryCost)]
273
pub struct Create2 {
274
    /// Identifier for what kind of handshake this is.
275
    handshake_type: HandshakeType,
276
    /// Body of the handshake.
277
    handshake: Vec<u8>,
278
}
279
impl Body for Create2 {
280
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
281
4
        w.write_u16(self.handshake_type.into());
282
4
        let handshake_len = self
283
4
            .handshake
284
4
            .len()
285
4
            .try_into()
286
4
            .map_err(|_| EncodeError::BadLengthValue)?;
287
4
        w.write_u16(handshake_len);
288
4
        w.write_all(&self.handshake[..]);
289
4
        Ok(())
290
4
    }
291
}
292
impl Readable for Create2 {
293
62
    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
294
62
        let handshake_type = HandshakeType::from(b.take_u16()?);
295
62
        let hlen = b.take_u16()?;
296
62
        let handshake = b.take(hlen as usize)?.into();
297
62
        Ok(Create2 {
298
62
            handshake_type,
299
62
            handshake,
300
62
        })
301
62
    }
302
}
303
impl Create2 {
304
    /// Wrap a typed handshake as a Create2 message
305
60
    pub fn new<B>(handshake_type: HandshakeType, handshake: B) -> Self
306
60
    where
307
60
        B: Into<Vec<u8>>,
308
    {
309
60
        let handshake = handshake.into();
310
60
        Create2 {
311
60
            handshake_type,
312
60
            handshake,
313
60
        }
314
60
    }
315

            
316
    /// Return the type of this handshake.
317
310
    pub fn handshake_type(&self) -> HandshakeType {
318
310
        self.handshake_type
319
310
    }
320

            
321
    /// Return the body of this handshake.
322
1178
    pub fn body(&self) -> &[u8] {
323
1178
        &self.handshake[..]
324
1178
    }
325
}
326

            
327
/// A Created2 message completes a circuit-creation handshake.
328
///
329
/// When a relay receives a valid Create2 message that it can handle, it
330
/// establishes the circuit and replies with a Created2.
331
#[derive(Clone, Debug, Deftly)]
332
#[derive_deftly(HasMemoryCost)]
333
pub struct Created2 {
334
    /// Body of the handshake reply
335
    handshake: Vec<u8>,
336
}
337
impl Created2 {
338
    /// Create a new Created2 to hold a given handshake.
339
90
    pub fn new<B>(handshake: B) -> Self
340
90
    where
341
90
        B: Into<Vec<u8>>,
342
    {
343
90
        let handshake = handshake.into();
344
90
        Created2 { handshake }
345
90
    }
346
    /// Consume this created2 cell and return its body.
347
1426
    pub fn into_body(self) -> Vec<u8> {
348
1426
        self.handshake
349
1426
    }
350
}
351
impl Body for Created2 {
352
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
353
4
        let handshake_len = self
354
4
            .handshake
355
4
            .len()
356
4
            .try_into()
357
4
            .map_err(|_| EncodeError::BadLengthValue)?;
358
4
        w.write_u16(handshake_len);
359
4
        w.write_all(&self.handshake[..]);
360
4
        Ok(())
361
4
    }
362
}
363
impl Readable for Created2 {
364
62
    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
365
62
        let hlen = b.take_u16()?;
366
62
        let handshake = b.take(hlen as usize)?.into();
367
62
        Ok(Created2 { handshake })
368
62
    }
369
}
370

            
371
/// A Relay cell - that is, one transmitted over a circuit.
372
///
373
/// Once a circuit has been established, relay cells can be sent over
374
/// it.  Clients can send relay cells to any relay on the circuit. Any
375
/// relay on the circuit can send relay cells to the client, either
376
/// directly (if it is the first hop), or indirectly through the
377
/// intermediate hops.
378
///
379
/// A different protocol is defined over the relay cells; it is implemented
380
/// in the [crate::relaycell] module.
381
#[derive(Clone, Educe, derive_more::From, Deftly)]
382
#[derive_deftly(HasMemoryCost)]
383
#[educe(Debug)]
384
pub struct Relay {
385
    /// The contents of the relay cell as encoded for transfer.
386
    ///
387
    /// TODO(nickm): It's nice that this is boxed, since we don't want to copy
388
    /// cell data all over the place. But unfortunately, there are some other
389
    /// places where we _don't_ Box things that we should, and more copies than
390
    /// necessary happen. We should refactor our data handling until we're mostly
391
    /// moving around pointers rather than copying data;  see ticket #7.
392
    #[educe(Debug(method = "skip_fmt"))]
393
    body: BoxedCellBody,
394
}
395
impl Relay {
396
    /// Construct a Relay message from a slice containing its contents.
397
140
    pub fn new<P>(body: P) -> Self
398
140
    where
399
140
        P: AsRef<[u8]>,
400
    {
401
140
        let body = body.as_ref();
402
140
        let mut r = [0_u8; CELL_DATA_LEN];
403
        // TODO: This will panic if body is too long, but that would be a
404
        // programming error anyway.
405
140
        r[..body.len()].copy_from_slice(body);
406
140
        Relay { body: Box::new(r) }
407
140
    }
408
    /// Construct a Relay message from its body.
409
62
    pub fn from_raw(body: RawCellBody) -> Self {
410
62
        Relay {
411
62
            body: Box::new(body),
412
62
        }
413
62
    }
414
    /// Consume this Relay message and return a BoxedCellBody for
415
    /// encryption/decryption.
416
143158
    pub fn into_relay_body(self) -> BoxedCellBody {
417
143158
        self.body
418
143158
    }
419
    /// Wrap this Relay message into a RelayMsg as a RELAY_EARLY cell.
420
62
    pub fn into_early(self) -> AnyChanMsg {
421
62
        AnyChanMsg::RelayEarly(RelayEarly(self))
422
62
    }
423
}
424
impl Body for Relay {
425
12
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
426
12
        w.write_all(&self.body[..]);
427
12
        Ok(())
428
12
    }
429
}
430
impl Readable for Relay {
431
372
    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
432
372
        let mut body = Box::new([0_u8; CELL_DATA_LEN]);
433
372
        body.copy_from_slice(b.take(CELL_DATA_LEN)?);
434
372
        Ok(Relay { body })
435
372
    }
436
}
437

            
438
/// A Relay cell that is allowed to contain a CREATE message.
439
///
440
/// Only a limited number of these may be sent on each circuit.
441
#[derive(Clone, Debug, derive_more::Deref, derive_more::From, derive_more::Into, Deftly)]
442
#[derive_deftly(HasMemoryCost)]
443
pub struct RelayEarly(Relay);
444
impl Readable for RelayEarly {
445
62
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
446
62
        Ok(RelayEarly(Relay::take_from(r)?))
447
62
    }
448
}
449
impl Body for RelayEarly {
450
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
451
4
        self.0.encode_onto(w)
452
4
    }
453
}
454
impl RelayEarly {
455
    /// Consume this RelayEarly message and return a BoxedCellBody for
456
    /// encryption/decryption.
457
    //
458
    // (Since this method takes `self` by value, we can't take advantage of
459
    // Deref.)
460
2356
    pub fn into_relay_body(self) -> BoxedCellBody {
461
2356
        self.0.body
462
2356
    }
463
}
464

            
465
/// The Destroy message tears down a circuit.
466
///
467
/// On receiving a Destroy message, a Tor implementation should
468
/// tear down the associated circuit, and pass the destroy message
469
/// down the circuit to later/earlier hops on the circuit (if any).
470
#[derive(Clone, Debug, Deftly)]
471
#[derive_deftly(HasMemoryCost)]
472
pub struct Destroy {
473
    /// Reason code given for tearing down this circuit
474
    reason: DestroyReason,
475
}
476
impl Destroy {
477
    /// Create a new destroy cell.
478
    ///
479
    /// If generating a new destroy cell,
480
    /// you should always create it with [`DestroyReason::NONE`].
481
    ///
482
    /// `tor-spec/tearing-down-circuits.md`:
483
    ///
484
    /// > Implementations SHOULD always use the NONE reason to avoid side channels: [...]
485
6138
    pub fn new(reason: DestroyReason) -> Self {
486
6138
        Destroy { reason }
487
6138
    }
488
    /// Return the provided reason for destroying the circuit.
489
1488
    pub fn reason(&self) -> DestroyReason {
490
1488
        self.reason
491
1488
    }
492
}
493
impl Body for Destroy {
494
20
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
495
20
        w.write_u8(self.reason.into());
496
20
        Ok(())
497
20
    }
498
}
499
impl Readable for Destroy {
500
496
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
501
496
        let reason = r.take_u8()?.into();
502
496
        Ok(Destroy { reason })
503
496
    }
504
}
505

            
506
caret_int! {
507
    /// Declared reason for ending a circuit.
508
    #[derive(Deftly)]
509
    #[derive_deftly(HasMemoryCost)]
510
    pub struct DestroyReason(u8) {
511
        /// No reason given.
512
        ///
513
        /// This is the only reason that clients send.
514
        NONE = 0,
515
        /// Protocol violation
516
        PROTOCOL = 1,
517
        /// Internal error.
518
        INTERNAL = 2,
519
        /// Client sent a TRUNCATE command.
520
        REQUESTED = 3,
521
        /// Relay is hibernating and not accepting requests
522
        HIBERNATING = 4,
523
        /// Ran out of memory, sockets, or circuit IDs
524
        RESOURCELIMIT = 5,
525
        /// Couldn't connect to relay.
526
        CONNECTFAILED = 6,
527
        /// Connected to a relay, but its OR identity wasn't as requested.
528
        OR_IDENTITY = 7,
529
        /// One of the OR channels carrying this circuit died.
530
        CHANNEL_CLOSED = 8,
531
        /// Circuit expired for being too dirty or old
532
        FINISHED = 9,
533
        /// Circuit construction took too long
534
        TIMEOUT = 10,
535
        /// Circuit was destroyed w/o client truncate (?)
536
        DESTROYED = 11,
537
        /// Request for unknown onion service
538
        NOSUCHSERVICE = 12
539
    }
540
}
541

            
542
impl DestroyReason {
543
    /// Return a human-readable string for this reason.
544
376
    pub fn human_str(&self) -> &'static str {
545
376
        match *self {
546
            DestroyReason::NONE => "No reason",
547
            DestroyReason::PROTOCOL => "Protocol violation",
548
            DestroyReason::INTERNAL => "Internal error",
549
            DestroyReason::REQUESTED => "Client sent a TRUNCATE command",
550
372
            DestroyReason::HIBERNATING => "Relay is hibernating and not accepting requests",
551
            DestroyReason::RESOURCELIMIT => "Relay ran out of resources",
552
2
            DestroyReason::CONNECTFAILED => "Couldn't connect to relay",
553
            DestroyReason::OR_IDENTITY => "Connected to relay with different OR identity",
554
            DestroyReason::CHANNEL_CLOSED => "The OR channels carrying this circuit died",
555
            DestroyReason::FINISHED => "Circuit expired for being too dirty or old",
556
            DestroyReason::TIMEOUT => "Circuit construction took too long",
557
            DestroyReason::DESTROYED => "Circuit was destroyed without client truncate",
558
            DestroyReason::NOSUCHSERVICE => "No such onion service",
559
2
            _ => "Unrecognized reason",
560
        }
561
376
    }
562
}
563

            
564
/// The netinfo message ends channel negotiation.
565
///
566
/// It tells the other party on the channel our view of the current time,
567
/// our own list of public addresses, and our view of its address.
568
///
569
/// When we get a netinfo cell, we can start creating circuits on a
570
/// channel and sending data.
571
#[derive(Clone, Debug, Deftly)]
572
#[derive_deftly(HasMemoryCost)]
573
pub struct Netinfo {
574
    /// Time when this cell was sent, or 0 if this cell is sent by a client.
575
    ///
576
    /// TODO-SPEC(nickm): Y2038 issue here.  Better add a new handshake version
577
    /// to solve it.  See
578
    /// [torspec#80](https://gitlab.torproject.org/tpo/core/torspec/-/issues/80).
579
    timestamp: u32,
580
    /// Observed address for party that did not send the netinfo cell.
581
    their_addr: Option<IpAddr>,
582
    /// Canonical addresses for the party that did send the netinfo cell.
583
    my_addr: Vec<IpAddr>,
584
}
585
/// helper: encode a single address in the form that netinfo messages expect
586
79
fn enc_one_netinfo_addr<W: Writer + ?Sized>(w: &mut W, addr: &IpAddr) {
587
79
    match addr {
588
71
        IpAddr::V4(ipv4) => {
589
71
            w.write_u8(0x04); // type.
590
71
            w.write_u8(4); // length.
591
71
            w.write_all(&ipv4.octets()[..]);
592
71
        }
593
8
        IpAddr::V6(ipv6) => {
594
8
            w.write_u8(0x06); // type.
595
8
            w.write_u8(16); // length.
596
8
            w.write_all(&ipv6.octets()[..]);
597
8
        }
598
    }
599
79
}
600
/// helper: take an address as encoded in a netinfo message
601
1860
fn take_one_netinfo_addr(r: &mut Reader<'_>) -> Result<Option<IpAddr>> {
602
1860
    let atype = r.take_u8()?;
603
1860
    let alen = r.take_u8()?;
604
1860
    let abody = r.take(alen as usize)?;
605
1860
    match (atype, alen) {
606
        (0x04, 4) => {
607
1426
            let bytes = [abody[0], abody[1], abody[2], abody[3]];
608
1426
            Ok(Some(IpAddr::V4(bytes.into())))
609
        }
610
        (0x06, 16) => {
611
            // TODO(nickm) is there a better way?
612
186
            let mut bytes = [0_u8; 16];
613
186
            bytes.copy_from_slice(abody);
614
186
            Ok(Some(IpAddr::V6(bytes.into())))
615
        }
616
248
        (_, _) => Ok(None),
617
    }
618
1860
}
619
impl Netinfo {
620
    /// Construct a new Netinfo to be sent by a client.
621
248
    pub fn from_client(their_addr: Option<IpAddr>) -> Self {
622
248
        Netinfo {
623
248
            timestamp: 0, // clients don't report their timestamps.
624
248
            their_addr,
625
248
            my_addr: Vec::new(), // clients don't report their addrs.
626
248
        }
627
248
    }
628
    /// Construct a new Netinfo to be sent by a relay
629
6
    pub fn from_relay<V>(timestamp: u32, their_addr: Option<IpAddr>, my_addrs: V) -> Self
630
6
    where
631
6
        V: Into<Vec<IpAddr>>,
632
    {
633
6
        let my_addr = my_addrs.into();
634
6
        Netinfo {
635
6
            timestamp,
636
6
            their_addr,
637
6
            my_addr,
638
6
        }
639
6
    }
640
    /// Return the time reported in this NETINFO cell.
641
434
    pub fn timestamp(&self) -> Option<std::time::SystemTime> {
642
        use std::time::{Duration, SystemTime};
643
434
        if self.timestamp == 0 {
644
124
            None
645
        } else {
646
310
            Some(SystemTime::UNIX_EPOCH + Duration::from_secs(self.timestamp.into()))
647
        }
648
434
    }
649

            
650
    /// Return a reference to the their address field.
651
    ///
652
    /// None is returned if their address is 0.0.0.0/:: (unspecified).
653
124
    pub fn their_addr(&self) -> Option<&IpAddr> {
654
124
        self.their_addr.as_ref()
655
124
    }
656

            
657
    /// Return a reference to the my address field.
658
124
    pub fn my_addrs(&self) -> &[IpAddr] {
659
124
        &self.my_addr
660
124
    }
661
}
662
impl Body for Netinfo {
663
67
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
664
67
        w.write_u32(self.timestamp);
665
67
        let their_addr = self
666
67
            .their_addr
667
67
            .unwrap_or_else(|| Ipv4Addr::UNSPECIFIED.into());
668
67
        enc_one_netinfo_addr(w, &their_addr);
669
67
        let n_addrs: u8 = self
670
67
            .my_addr
671
67
            .len()
672
67
            .try_into()
673
67
            .map_err(|_| EncodeError::BadLengthValue)?;
674
67
        w.write_u8(n_addrs);
675
67
        for addr in &self.my_addr {
676
12
            enc_one_netinfo_addr(w, addr);
677
12
        }
678
67
        Ok(())
679
67
    }
680
}
681
impl Readable for Netinfo {
682
930
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
683
930
        let timestamp = r.take_u32()?;
684
943
        let their_addr = take_one_netinfo_addr(r)?.filter(|a| !a.is_unspecified());
685
930
        let my_n_addrs = r.take_u8()?;
686
930
        let mut my_addr = Vec::with_capacity(my_n_addrs as usize);
687
930
        for _ in 0..my_n_addrs {
688
930
            if let Some(a) = take_one_netinfo_addr(r)? {
689
806
                my_addr.push(a);
690
806
            }
691
        }
692
930
        Ok(Netinfo {
693
930
            timestamp,
694
930
            their_addr,
695
930
            my_addr,
696
930
        })
697
930
    }
698
}
699

            
700
/// A Versions message begins channel negotiation.
701
///
702
/// Every channel must begin by sending a Versions message.  This message
703
/// lists the link protocol versions that this Tor implementation supports.
704
///
705
/// Note that we should never actually send Versions cells using the
706
/// usual channel cell encoding: Versions cells _always_ use two-byte
707
/// circuit IDs, whereas all the other cell types use four-byte
708
/// circuit IDs [assuming a non-obsolete version is negotiated].
709
#[derive(Clone, Debug, Deftly)]
710
#[derive_deftly(HasMemoryCost)]
711
pub struct Versions {
712
    /// List of supported link protocol versions
713
    versions: Vec<u16>,
714
}
715
impl Versions {
716
    /// Construct a new Versions message using a provided list of link
717
    /// protocols.
718
    ///
719
    /// Returns an error if the list of versions is too long.
720
80
    pub fn new<B>(vs: B) -> crate::Result<Self>
721
80
    where
722
80
        B: Into<Vec<u16>>,
723
    {
724
80
        let versions = vs.into();
725
80
        if versions.len() < (u16::MAX / 2) as usize {
726
80
            Ok(Self { versions })
727
        } else {
728
            Err(crate::Error::CantEncode("Too many versions"))
729
        }
730
80
    }
731
    /// Encode this VERSIONS cell in the manner expected for a handshake.
732
    ///
733
    /// (That's different from a standard cell encoding, since we
734
    /// have not negotiated versions yet, and so our circuit-ID length
735
    /// is an obsolete 2 bytes).
736
2232
    pub fn encode_for_handshake(self) -> EncodeResult<Vec<u8>> {
737
2232
        let mut v = Vec::new();
738
2232
        v.write_u16(0); // obsolete circuit ID length.
739
2232
        v.write_u8(ChanCmd::VERSIONS.into());
740
2232
        v.write_u16((self.versions.len() * 2) as u16); // message length.
741
2232
        self.encode_onto(&mut v)?;
742
2232
        Ok(v)
743
2232
    }
744
    /// Return the best (numerically highest) link protocol that is
745
    /// shared by this versions cell and my_protos.
746
1612
    pub fn best_shared_link_protocol(&self, my_protos: &[u16]) -> Option<u16> {
747
        // NOTE: this implementation is quadratic, but it shouldn't matter
748
        // much so long as my_protos is small.
749
1612
        let p = my_protos
750
1612
            .iter()
751
3436
            .filter(|p| self.versions.contains(p))
752
2816
            .fold(0_u16, |a, b| u16::max(a, *b));
753
1612
        if p == 0 { None } else { Some(p) }
754
1612
    }
755
}
756
impl Body for Versions {
757
2356
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
758
4154
        for v in &self.versions {
759
4154
            w.write_u16(*v);
760
4154
        }
761
2356
        Ok(())
762
2356
    }
763
}
764
impl Readable for Versions {
765
1736
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
766
1736
        let mut versions = Vec::new();
767
6076
        while r.remaining() > 0 {
768
4340
            versions.push(r.take_u16()?);
769
        }
770
1736
        Ok(Versions { versions })
771
1736
    }
772
}
773

            
774
caret_int! {
775
    /// A ChanCmd is the type of a channel cell.  The value of the ChanCmd
776
    /// indicates the meaning of the cell, and (possibly) its length.
777
    #[derive(Deftly)]
778
    #[derive_deftly(HasMemoryCost)]
779
    pub struct PaddingNegotiateCmd(u8) {
780
        /// Start padding
781
        START = 2,
782

            
783
        /// Stop padding
784
        STOP = 1,
785
    }
786
}
787

            
788
/// A PaddingNegotiate message is used to negotiate channel padding.
789
///
790
/// Sent by a client to its guard node,
791
/// to instruct the relay to enable/disable channel padding.
792
/// (Not relevant for channels used only for directory lookups,
793
/// nor inter-relay channels.)
794
/// See `padding-spec.txt`, section 2.2.
795
///
796
/// This message is constructed in the channel manager and transmitted by the reactor.
797
///
798
/// The `Default` impl is the same as [`start_default()`](PaddingNegotiate::start_default`)
799
#[derive(Clone, Debug, Eq, PartialEq, Deftly)]
800
#[derive_deftly(HasMemoryCost)]
801
pub struct PaddingNegotiate {
802
    /// Whether to start or stop padding
803
    command: PaddingNegotiateCmd,
804
    /// Suggested lower-bound value for inter-packet timeout in msec.
805
    // TODO(nickm) is that right?
806
    ito_low_ms: u16,
807
    /// Suggested upper-bound value for inter-packet timeout in msec.
808
    // TODO(nickm) is that right?
809
    ito_high_ms: u16,
810
}
811
impl PaddingNegotiate {
812
    /// Create a new PADDING_NEGOTIATE START message requesting consensus timing parameters.
813
    ///
814
    /// This message restores the state to the one which exists at channel startup.
815
9796
    pub fn start_default() -> Self {
816
        // Tor Spec section 7.3, padding-spec section 2.5.
817
9796
        Self {
818
9796
            command: PaddingNegotiateCmd::START,
819
9796
            ito_low_ms: 0,
820
9796
            ito_high_ms: 0,
821
9796
        }
822
9796
    }
823

            
824
    /// Create a new PADDING_NEGOTIATE START message.
825
62
    pub fn start(ito_low: IntegerMilliseconds<u16>, ito_high: IntegerMilliseconds<u16>) -> Self {
826
        // Tor Spec section 7.3
827
62
        Self {
828
62
            command: PaddingNegotiateCmd::START,
829
62
            ito_low_ms: ito_low.as_millis(),
830
62
            ito_high_ms: ito_high.as_millis(),
831
62
        }
832
62
    }
833

            
834
    /// Create a new PADDING_NEGOTIATE STOP message.
835
2914
    pub fn stop() -> Self {
836
        // Tor Spec section 7.3
837
2914
        Self {
838
2914
            command: PaddingNegotiateCmd::STOP,
839
2914
            ito_low_ms: 0,
840
2914
            ito_high_ms: 0,
841
2914
        }
842
2914
    }
843

            
844
    /// Construct from the three fields: command, low_ms, high_ms, as a tuple
845
    ///
846
    /// For testing only
847
    #[cfg(feature = "testing")]
848
1488
    pub fn from_raw(command: PaddingNegotiateCmd, ito_low_ms: u16, ito_high_ms: u16) -> Self {
849
1488
        PaddingNegotiate {
850
1488
            command,
851
1488
            ito_low_ms,
852
1488
            ito_high_ms,
853
1488
        }
854
1488
    }
855
}
856
impl Default for PaddingNegotiate {
857
5456
    fn default() -> Self {
858
5456
        Self::start_default()
859
5456
    }
860
}
861

            
862
impl Body for PaddingNegotiate {
863
8
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
864
8
        w.write_u8(0); // version
865
8
        w.write_u8(self.command.get());
866
8
        w.write_u16(self.ito_low_ms);
867
8
        w.write_u16(self.ito_high_ms);
868
8
        Ok(())
869
8
    }
870
}
871
impl Readable for PaddingNegotiate {
872
186
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
873
186
        let v = r.take_u8()?;
874
186
        if v != 0 {
875
62
            return Err(Error::InvalidMessage(
876
62
                "Unrecognized padding negotiation version".into(),
877
62
            ));
878
124
        }
879
124
        let command = r.take_u8()?.into();
880
124
        let ito_low_ms = r.take_u16()?;
881
124
        let ito_high_ms = r.take_u16()?;
882
124
        Ok(PaddingNegotiate {
883
124
            command,
884
124
            ito_low_ms,
885
124
            ito_high_ms,
886
124
        })
887
186
    }
888
}
889

            
890
/// A single certificate in a Certs cell.
891
///
892
/// The formats used here are implemented in tor-cert. Ed25519Cert is the
893
/// most common.
894
#[derive(Clone, Debug, Deftly)]
895
#[derive_deftly(HasMemoryCost)]
896
struct TorCert {
897
    /// Type code for this certificate.
898
    certtype: u8,
899
    /// Encoded certificate
900
    cert: Vec<u8>,
901
}
902
/// encode a single TorCert `c` onto a Writer `w`.
903
20
fn enc_one_tor_cert<W: Writer + ?Sized>(w: &mut W, c: &TorCert) -> EncodeResult<()> {
904
20
    w.write_u8(c.certtype);
905
20
    let cert_len: u16 = c
906
20
        .cert
907
20
        .len()
908
20
        .try_into()
909
20
        .map_err(|_| EncodeError::BadLengthValue)?;
910
20
    w.write_u16(cert_len);
911
20
    w.write_all(&c.cert[..]);
912
20
    Ok(())
913
20
}
914
/// Try to extract a TorCert from the reader `r`.
915
744
fn take_one_tor_cert(r: &mut Reader<'_>) -> Result<TorCert> {
916
744
    let certtype = r.take_u8()?;
917
620
    let certlen = r.take_u16()?;
918
620
    let cert = r.take(certlen as usize)?;
919
620
    Ok(TorCert {
920
620
        certtype,
921
620
        cert: cert.into(),
922
620
    })
923
744
}
924
/// A Certs message is used as part of the channel handshake to send
925
/// additional certificates.
926
///
927
/// These certificates are not presented as part of the TLS handshake.
928
/// Originally this was meant to make Tor TLS handshakes look "normal", but
929
/// nowadays it serves less purpose, especially now that we have TLS 1.3.
930
///
931
/// Every relay sends this message as part of channel negotiation;
932
/// clients do not send them.
933
#[derive(Clone, Debug, Deftly)]
934
#[derive_deftly(HasMemoryCost)]
935
pub struct Certs {
936
    /// The certificates in this cell
937
    certs: Vec<TorCert>,
938
}
939
impl Certs {
940
    /// Return a new empty certs cell.
941
1612
    pub fn new_empty() -> Self {
942
1612
        Certs { certs: Vec::new() }
943
1612
    }
944
    /// Add a new encoded certificate to this cell.
945
    ///
946
    /// Does not check anything about the well-formedness of the certificate.
947
92
    pub fn push_cert_body<B>(&mut self, certtype: tor_cert::CertType, cert: B)
948
92
    where
949
92
        B: Into<Vec<u8>>,
950
    {
951
92
        let certtype = certtype.into();
952
92
        let cert = cert.into();
953
92
        self.certs.push(TorCert { certtype, cert });
954
92
    }
955

            
956
    /// Add a new encoded certificate to this cell,
957
    /// taking taking the type from the certificate itself.
958
    #[cfg(feature = "relay")]
959
12
    pub fn push_cert<C>(&mut self, cert: &C)
960
12
    where
961
12
        C: tor_cert::EncodedCert,
962
    {
963
12
        self.push_cert_body(cert.cert_type(), cert.encoded());
964
12
    }
965

            
966
    /// Return the body of the certificate tagged with 'tp', if any.
967
2976
    pub fn cert_body(&self, tp: tor_cert::CertType) -> Option<&[u8]> {
968
2976
        let tp: u8 = tp.into();
969
2976
        self.certs
970
2976
            .iter()
971
7922
            .find(|c| c.certtype == tp)
972
3018
            .map(|c| &c.cert[..])
973
2976
    }
974

            
975
    /// Look for a certificate of type 'tp' in this cell; return it if
976
    /// there is one.
977
1426
    pub fn parse_ed_cert(&self, tp: tor_cert::CertType) -> crate::Result<tor_cert::KeyUnknownCert> {
978
1426
        let body = self
979
1426
            .cert_body(tp)
980
1429
            .ok_or_else(|| crate::Error::ChanProto(format!("Missing {} certificate", tp)))?;
981

            
982
1240
        let cert = tor_cert::Ed25519Cert::decode(body).map_err(|be| crate::Error::BytesErr {
983
62
            err: be,
984
            parsed: "ed25519 certificate",
985
63
        })?;
986
1178
        if cert.peek_cert_type() != tp {
987
            return Err(crate::Error::ChanProto(format!(
988
                "Found a {} certificate labeled as {}",
989
                cert.peek_cert_type(),
990
                tp
991
            )));
992
1178
        }
993

            
994
1178
        Ok(cert)
995
1426
    }
996
}
997

            
998
impl Body for Certs {
999
16
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
16
        let n_certs: u8 = self
16
            .certs
16
            .len()
16
            .try_into()
16
            .map_err(|_| EncodeError::BadLengthValue)?;
16
        w.write_u8(n_certs);
32
        for c in &self.certs {
20
            enc_one_tor_cert(w, c)?;
        }
16
        Ok(())
16
    }
}
impl Readable for Certs {
1116
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1116
        let n = r.take_u8()?;
1116
        let mut certs = Vec::new();
1116
        for _ in 0..n {
744
            certs.push(take_one_tor_cert(r)?);
        }
992
        Ok(Certs { certs })
1116
    }
}
/// Length of the body for an authentication challenge
const CHALLENGE_LEN: usize = 32;
/// An AuthChallenge message is part of negotiation, sent by
/// responders to initiators.
///
/// The AuthChallenge cell is used to ensure that some unpredictable material
/// has been sent on the channel, and to tell the initiator what
/// authentication methods will be accepted.
///
/// Clients can safely ignore this message: they don't need to authenticate.
#[derive(Clone, Debug, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct AuthChallenge {
    /// Random challenge to be used in generating response
    challenge: [u8; CHALLENGE_LEN],
    /// List of permitted authentication methods
    methods: Vec<u16>,
}
impl AuthChallenge {
    /// Construct a new AuthChallenge cell with a given challenge
    /// value (chosen randomly) and a set of acceptable authentication methods.
14
    pub fn new<B, M>(challenge: B, methods: M) -> Self
14
    where
14
        B: Into<[u8; CHALLENGE_LEN]>,
14
        M: Into<Vec<u16>>,
    {
14
        AuthChallenge {
14
            challenge: challenge.into(),
14
            methods: methods.into(),
14
        }
14
    }
    /// Return a reference to the list of methods.
    pub fn methods(&self) -> &[u16] {
        &self.methods
    }
}
impl Body for AuthChallenge {
16
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
16
        w.write_all(&self.challenge[..]);
16
        let n_methods = self
16
            .methods
16
            .len()
16
            .try_into()
16
            .map_err(|_| EncodeError::BadLengthValue)?;
16
        w.write_u16(n_methods);
20
        for m in self.methods {
20
            w.write_u16(m);
20
        }
16
        Ok(())
16
    }
}
impl Readable for AuthChallenge {
1116
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
        //let challenge = r.take(CHALLENGE_LEN)?.into();
1116
        let challenge = r.extract()?;
1116
        let n_methods = r.take_u16()?;
1116
        let mut methods = Vec::new();
1116
        for _ in 0..n_methods {
1798
            methods.push(r.take_u16()?);
        }
1116
        Ok(AuthChallenge { challenge, methods })
1116
    }
}
/// Part of negotiation: sent by initiators to responders.
///
/// The Authenticate cell proves the initiator's identity to the
/// responder, even if TLS client authentication was not used.
///
/// Clients do not use this.
#[derive(Clone, Debug, Deftly, Eq, PartialEq)]
#[derive_deftly(HasMemoryCost)]
pub struct Authenticate {
    /// Authentication method in use
    authtype: u16,
    /// Encoded authentication object
    auth: Vec<u8>,
}
impl Authenticate {
    /// The signature field length.
    const SIG_LEN: usize = 64;
    /// The body length that is all fields except the rand and signature.
    pub const BODY_LEN: usize = 264;
    /// Create a new Authenticate message from a given type and body.
2
    pub fn new<B>(authtype: u16, body: B) -> Self
2
    where
2
        B: Into<Vec<u8>>,
    {
2
        Authenticate {
2
            authtype,
2
            auth: body.into(),
2
        }
2
    }
    /// Return the authentication type value.
    pub fn auth_type(&self) -> u16 {
        self.authtype
    }
    /// Return a referrence to the body of the cell that is all fields minus the random bytes
    /// located before the signature.
    pub fn body_no_rand(&self) -> Result<&[u8]> {
        // The RAND field length.
        const RAND_LEN: usize = 24;
        let body = self.body()?;
        let body_end_offset = body.len().checked_sub(RAND_LEN).ok_or(Error::MissingData)?;
        Ok(&body[..body_end_offset])
    }
    /// Return a referrence to the body of the cell that is all fields except the signature.
    pub fn body(&self) -> Result<&[u8]> {
        let auth = self.auth();
        let sig_end_offset = auth
            .len()
            .checked_sub(Self::SIG_LEN)
            .ok_or(Error::MissingData)?;
        Ok(&auth[..sig_end_offset])
    }
    /// Return a reference to the authentcation object.
    pub fn auth(&self) -> &[u8] {
        &self.auth
    }
    /// Return a reference to the signature bytes.
    pub fn sig(&self) -> Result<&[u8; Self::SIG_LEN]> {
        let auth = self.auth();
        let sig_start_offset = auth
            .len()
            .checked_sub(Self::SIG_LEN)
            .ok_or(Error::MissingData)?;
        (&self.auth[sig_start_offset..])
            .try_into()
            .map_err(|_| Error::Bug(tor_error::internal!("Failed to get signature bytes")))
    }
}
impl Body for Authenticate {
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
4
        w.write_u16(self.authtype);
4
        let authlen = self
4
            .auth
4
            .len()
4
            .try_into()
4
            .map_err(|_| EncodeError::BadLengthValue)?;
4
        w.write_u16(authlen);
4
        w.write_all(&self.auth[..]);
4
        Ok(())
4
    }
}
impl Readable for Authenticate {
62
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
62
        let authtype = r.take_u16()?;
62
        let authlen = r.take_u16()?;
62
        let auth = r.take(authlen as usize)?.into();
62
        Ok(Authenticate { authtype, auth })
62
    }
}
/// Holds any message whose command we don't recognize.
///
/// Well-behaved Tor implementations are required to ignore commands
/// like this.
///
/// TODO: I believe that this is not a risky case of Postel's law,
/// since it is only for channels, but we should be careful here.
#[derive(Clone, Debug, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Unrecognized {
    /// The channel command that we got with this cell
    cmd: ChanCmd,
    /// The contents of the cell
    content: Vec<u8>,
}
impl Unrecognized {
    /// Construct a new cell of arbitrary or unrecognized type.
6
    pub fn new<B>(cmd: ChanCmd, content: B) -> Self
6
    where
6
        B: Into<Vec<u8>>,
    {
6
        let content = content.into();
6
        Unrecognized { cmd, content }
6
    }
    /// Return the command from this cell.
248
    pub fn cmd(&self) -> ChanCmd {
248
        self.cmd
248
    }
    /// Take an unrecognized cell's body from a reader `r`, and apply
    /// the given command to it.
248
    pub fn decode_with_cmd(cmd: ChanCmd, r: &mut Reader<'_>) -> Result<Unrecognized> {
248
        let mut u = Unrecognized::take_from(r)?;
248
        u.cmd = cmd;
248
        Ok(u)
248
    }
}
impl Body for Unrecognized {
12
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
12
        w.write_all(&self.content[..]);
12
        Ok(())
12
    }
}
impl Readable for Unrecognized {
248
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
        Ok(Unrecognized {
248
            cmd: 0.into(),
248
            content: r.take(r.remaining())?.into(),
        })
248
    }
}
/// Helper: declare a From<> implementation from message types for
/// cells that don't take a circid.
macro_rules! msg_into_cell {
    ($body:ident) => {
        impl From<$body> for super::AnyChanCell {
124
            fn from(body: $body) -> super::AnyChanCell {
124
                super::AnyChanCell {
124
                    circid: None,
124
                    msg: body.into(),
124
                }
124
            }
        }
    };
}
msg_into_cell!(Padding);
msg_into_cell!(Vpadding);
msg_into_cell!(Netinfo);
msg_into_cell!(Versions);
msg_into_cell!(PaddingNegotiate);
msg_into_cell!(Certs);
msg_into_cell!(AuthChallenge);
msg_into_cell!(Authenticate);
/// Helper: declare a ChanMsg implementation for a message type that has a
/// fixed command.
//
// TODO: It might be better to merge Body with ChanMsg, 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_chanmsg {
    ($($body:ident,)*) =>
    {paste::paste!{
       $(impl crate::chancell::ChanMsg for $body {
16864
            fn cmd(&self) -> crate::chancell::ChanCmd { crate::chancell::ChanCmd::[< $body:snake:upper >] }
12
            fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()> {
12
                crate::chancell::msg::Body::encode_onto(self, w)
12
            }
1674
            fn decode_from_reader(cmd: ChanCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
1674
                if cmd != crate::chancell::ChanCmd::[< $body:snake:upper >] {
                    return Err(tor_bytes::Error::InvalidMessage(
                        format!("Expected {} command; got {cmd}", stringify!([< $body:snake:upper >])).into()
                    ));
1674
                }
1674
                crate::chancell::msg::Body::decode_from_reader(r)
1674
            }
        })*
    }}
}
// We implement ChanMsg for every body type, so that you can write code that does
// e.g. ChanCell<Relay>.
msg_impl_chanmsg!(
    Padding,
    Vpadding,
    Create,
    CreateFast,
    Create2,
    Created,
    CreatedFast,
    Created2,
    Relay,
    RelayEarly,
    Destroy,
    Netinfo,
    Versions,
    PaddingNegotiate,
    Certs,
    AuthChallenge,
    Authenticate,
);
#[cfg(test)]
mod test {
    // @@ begin test lint list maintained by maint/add_warning @@
    #![allow(clippy::bool_assert_comparison)]
    #![allow(clippy::clone_on_copy)]
    #![allow(clippy::dbg_macro)]
    #![allow(clippy::mixed_attributes_style)]
    #![allow(clippy::print_stderr)]
    #![allow(clippy::print_stdout)]
    #![allow(clippy::single_char_pattern)]
    #![allow(clippy::unwrap_used)]
    #![allow(clippy::unchecked_time_subtraction)]
    #![allow(clippy::useless_vec)]
    #![allow(clippy::needless_pass_by_value)]
    #![allow(clippy::string_slice)] // See arti#2571
    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
    use super::*;
    #[test]
    fn destroy_reason() {
        let r1 = DestroyReason::CONNECTFAILED;
        assert_eq!(r1.human_str(), "Couldn't connect to relay");
        let r2 = DestroyReason::from(200); // not a specified number.
        assert_eq!(r2.human_str(), "Unrecognized reason");
    }
}