1use std::num::NonZeroU32;
5
6use binrw::binrw;
7
8use super::{Packet, arch};
9
10impl Packet for GlobalRequest<'_> {}
11impl Packet for RequestSuccess {}
12impl Packet for ForwardingSuccess {}
13impl Packet for RequestFailure {}
14impl Packet for ChannelOpen<'_> {}
15impl Packet for ChannelOpenConfirmation {}
16impl Packet for ChannelOpenFailure<'_> {}
17impl Packet for ChannelWindowAdjust {}
18impl Packet for ChannelData<'_> {}
19impl Packet for ChannelExtendedData<'_> {}
20impl Packet for ChannelEof {}
21impl Packet for ChannelClose {}
22impl Packet for ChannelRequest<'_> {}
23impl Packet for ChannelSuccess {}
24impl Packet for ChannelFailure {}
25
26#[binrw]
30#[derive(Debug, Clone)]
31#[brw(big, magic = 80_u8)]
32pub struct GlobalRequest<'b> {
33 #[bw(calc = context.as_ascii())]
34 kind: arch::Ascii<'b>,
35
36 pub want_reply: arch::Bool,
38
39 #[br(args(kind))]
41 pub context: GlobalRequestContext<'b>,
42}
43
44#[binrw]
46#[derive(Debug, Clone)]
47#[brw(big)]
48#[br(import(kind: arch::Ascii<'_>))]
49pub enum GlobalRequestContext<'b> {
50 #[br(pre_assert(kind == GlobalRequestContext::TCPIP_FORWARD))]
53 TcpipForward {
54 bind_address: arch::Bytes<'b>,
56
57 bind_port: u32,
59 },
60
61 #[br(pre_assert(kind == GlobalRequestContext::CANCEL_TCPIP_FORWARD))]
64 CancelTcpipForward {
65 bind_address: arch::Bytes<'b>,
67
68 bind_port: u32,
70 },
71}
72
73impl GlobalRequestContext<'_> {
74 const TCPIP_FORWARD: arch::Ascii<'static> = arch::ascii!("tcpip-forward");
75 const CANCEL_TCPIP_FORWARD: arch::Ascii<'static> = arch::ascii!("cancel-tcpip-forward");
76
77 pub fn as_ascii(&self) -> arch::Ascii<'static> {
79 match self {
80 Self::TcpipForward { .. } => Self::TCPIP_FORWARD,
81 Self::CancelTcpipForward { .. } => Self::CANCEL_TCPIP_FORWARD,
82 }
83 }
84}
85#[binrw]
89#[derive(Debug, Clone)]
90#[brw(big, magic = 81_u8)]
91pub struct RequestSuccess;
92
93#[binrw]
98#[derive(Debug, Clone)]
99#[brw(big, magic = 81_u8)]
100pub struct ForwardingSuccess {
101 pub bound_port: u32,
103}
104
105#[binrw]
109#[derive(Debug, Clone)]
110#[brw(big, magic = 82_u8)]
111pub struct RequestFailure;
112
113#[binrw]
117#[derive(Debug, Clone)]
118#[brw(big, magic = 90_u8)]
119pub struct ChannelOpen<'b> {
120 #[bw(calc = context.as_ascii())]
121 kind: arch::Ascii<'b>,
122
123 pub sender_channel: u32,
125
126 pub initial_window_size: u32,
128
129 pub maximum_packet_size: u32,
131
132 #[br(args(kind))]
134 pub context: ChannelOpenContext<'b>,
135}
136
137#[binrw]
139#[derive(Debug, Clone)]
140#[brw(big)]
141#[br(import(kind: arch::Ascii<'_>))]
142pub enum ChannelOpenContext<'b> {
143 #[br(pre_assert(kind == ChannelOpenContext::SESSION))]
146 Session,
147
148 #[br(pre_assert(kind == ChannelOpenContext::X11))]
151 X11 {
152 originator_address: arch::Ascii<'b>,
154
155 originator_port: u32,
157 },
158
159 #[br(pre_assert(kind == ChannelOpenContext::FORWARDED_TCPIP))]
162 ForwardedTcpip {
163 address: arch::Ascii<'b>,
165
166 port: u32,
168
169 originator_address: arch::Ascii<'b>,
171
172 originator_port: u32,
174 },
175
176 #[br(pre_assert(kind == ChannelOpenContext::DIRECT_TCPIP))]
179 DirectTcpip {
180 address: arch::Ascii<'b>,
182
183 port: u32,
185
186 originator_address: arch::Ascii<'b>,
188
189 originator_port: u32,
191 },
192}
193
194impl ChannelOpenContext<'_> {
195 const SESSION: arch::Ascii<'static> = arch::ascii!("session");
196 const X11: arch::Ascii<'static> = arch::ascii!("x11");
197 const FORWARDED_TCPIP: arch::Ascii<'static> = arch::ascii!("forwarded-tcpip");
198 const DIRECT_TCPIP: arch::Ascii<'static> = arch::ascii!("direct-tcpip");
199
200 pub fn as_ascii(&self) -> arch::Ascii<'static> {
202 match self {
203 Self::Session { .. } => Self::SESSION,
204 Self::X11 { .. } => Self::X11,
205 Self::ForwardedTcpip { .. } => Self::FORWARDED_TCPIP,
206 Self::DirectTcpip { .. } => Self::DIRECT_TCPIP,
207 }
208 }
209}
210
211#[binrw]
215#[derive(Debug, Clone)]
216#[brw(big, magic = 91_u8)]
217pub struct ChannelOpenConfirmation {
218 pub recipient_channel: u32,
220
221 pub sender_channel: u32,
223
224 pub initial_window_size: u32,
226
227 pub maximum_packet_size: u32,
229}
230
231#[binrw]
235#[derive(Debug, Clone)]
236#[brw(big, magic = 92_u8)]
237pub struct ChannelOpenFailure<'b> {
238 pub recipient_channel: u32,
240
241 pub reason: ChannelOpenFailureReason,
243
244 pub description: arch::Utf8<'b>,
246
247 pub language: arch::Ascii<'b>,
249}
250
251#[binrw]
253#[derive(Debug, Clone)]
254#[brw(big)]
255pub enum ChannelOpenFailureReason {
256 #[brw(magic = 1_u32)]
258 AdministrativelyProhibited,
259
260 #[brw(magic = 2_u32)]
262 ConnectFailed,
263
264 #[brw(magic = 3_u32)]
266 UnknownChannelType,
267
268 #[brw(magic = 4_u32)]
270 ResourceShortage,
271
272 Other(u32),
277}
278
279#[binrw]
283#[derive(Debug, Clone)]
284#[brw(big, magic = 93_u8)]
285pub struct ChannelWindowAdjust {
286 pub recipient_channel: u32,
288
289 pub bytes_to_add: u32,
291}
292
293#[binrw]
297#[derive(Debug, Clone)]
298#[brw(big, magic = 94_u8)]
299pub struct ChannelData<'b> {
300 pub recipient_channel: u32,
302
303 pub data: arch::Bytes<'b>,
305}
306
307#[binrw]
311#[derive(Debug, Clone)]
312#[brw(big, magic = 95_u8)]
313pub struct ChannelExtendedData<'b> {
314 pub recipient_channel: u32,
316
317 pub data_type: NonZeroU32,
319
320 pub data: arch::Bytes<'b>,
322}
323
324#[binrw]
328#[derive(Debug, Clone)]
329#[brw(big, magic = 96_u8)]
330pub struct ChannelEof {
331 pub recipient_channel: u32,
333}
334
335#[binrw]
339#[derive(Debug, Clone)]
340#[brw(big, magic = 97_u8)]
341pub struct ChannelClose {
342 pub recipient_channel: u32,
344}
345
346#[binrw]
350#[derive(Debug, Clone)]
351#[brw(big, magic = 98_u8)]
352pub struct ChannelRequest<'b> {
353 pub recipient_channel: u32,
355
356 #[bw(calc = context.as_ascii())]
357 kind: arch::Ascii<'b>,
358
359 pub want_reply: arch::Bool,
361
362 #[br(args(kind))]
364 pub context: ChannelRequestContext<'b>,
365}
366
367#[binrw]
369#[derive(Debug, Clone)]
370#[brw(big)]
371#[br(import(kind: arch::Ascii<'_>))]
372pub enum ChannelRequestContext<'b> {
373 #[br(pre_assert(kind == ChannelRequestContext::PTY))]
376 Pty {
377 term: arch::Bytes<'b>,
379
380 width_chars: u32,
382
383 height_chars: u32,
385
386 width_pixels: u32,
388
389 height_pixels: u32,
391
392 modes: arch::Bytes<'b>,
394 },
395
396 #[br(pre_assert(kind == ChannelRequestContext::X11))]
399 X11 {
400 single_connection: arch::Bool,
402
403 x11_authentication_protocol: arch::Bytes<'b>,
405
406 x11_authentication_cookie: arch::Bytes<'b>,
408
409 x11_screen_number: u32,
411 },
412
413 #[br(pre_assert(kind == ChannelRequestContext::ENV))]
416 Env {
417 name: arch::Bytes<'b>,
419
420 value: arch::Bytes<'b>,
422 },
423
424 #[br(pre_assert(kind == ChannelRequestContext::SHELL))]
427 Shell,
428
429 #[br(pre_assert(kind == ChannelRequestContext::EXEC))]
432 Exec {
433 command: arch::Bytes<'b>,
435 },
436
437 #[br(pre_assert(kind == ChannelRequestContext::SUBSYSTEM))]
440 Subsystem {
441 name: arch::Bytes<'b>,
443 },
444
445 #[br(pre_assert(kind == ChannelRequestContext::WINDOW_CHANGE))]
448 WindowChange {
449 width_chars: u32,
451
452 height_chars: u32,
454
455 width_pixels: u32,
457
458 height_pixels: u32,
460 },
461
462 #[br(pre_assert(kind == ChannelRequestContext::XON_XOFF))]
465 XonXoff {
466 client_can_do: arch::Bool,
468 },
469
470 #[br(pre_assert(kind == ChannelRequestContext::SIGNAL))]
473 Signal {
474 name: arch::Bytes<'b>,
476 },
477
478 #[br(pre_assert(kind == ChannelRequestContext::EXIT_STATUS))]
481 ExitStatus {
482 code: u32,
484 },
485
486 #[br(pre_assert(kind == ChannelRequestContext::EXIT_SIGNAL))]
489 ExitSignal {
490 name: arch::Bytes<'b>,
492
493 core_dumped: arch::Bool,
495
496 error_message: arch::Utf8<'b>,
498
499 language: arch::Ascii<'b>,
501 },
502}
503
504impl ChannelRequestContext<'_> {
505 const PTY: arch::Ascii<'static> = arch::ascii!("pty-req");
506 const X11: arch::Ascii<'static> = arch::ascii!("x11-req");
507 const ENV: arch::Ascii<'static> = arch::ascii!("env");
508 const SHELL: arch::Ascii<'static> = arch::ascii!("shell");
509 const EXEC: arch::Ascii<'static> = arch::ascii!("exec");
510 const SUBSYSTEM: arch::Ascii<'static> = arch::ascii!("subsystem");
511 const WINDOW_CHANGE: arch::Ascii<'static> = arch::ascii!("window-change");
512 const XON_XOFF: arch::Ascii<'static> = arch::ascii!("xon-xoff");
513 const SIGNAL: arch::Ascii<'static> = arch::ascii!("signal");
514 const EXIT_STATUS: arch::Ascii<'static> = arch::ascii!("exit-status");
515 const EXIT_SIGNAL: arch::Ascii<'static> = arch::ascii!("exit-signal");
516
517 pub fn as_ascii(&self) -> arch::Ascii<'static> {
519 match self {
520 Self::Pty { .. } => Self::PTY,
521 Self::X11 { .. } => Self::X11,
522 Self::Env { .. } => Self::ENV,
523 Self::Shell { .. } => Self::SHELL,
524 Self::Exec { .. } => Self::EXEC,
525 Self::Subsystem { .. } => Self::SUBSYSTEM,
526 Self::WindowChange { .. } => Self::WINDOW_CHANGE,
527 Self::XonXoff { .. } => Self::XON_XOFF,
528 Self::Signal { .. } => Self::SIGNAL,
529 Self::ExitStatus { .. } => Self::EXIT_STATUS,
530 Self::ExitSignal { .. } => Self::EXIT_SIGNAL,
531 }
532 }
533}
534
535#[binrw]
539#[derive(Debug, Clone)]
540#[brw(big, magic = 99_u8)]
541pub struct ChannelSuccess {
542 pub recipient_channel: u32,
544}
545
546#[binrw]
550#[derive(Debug, Clone)]
551#[brw(big, magic = 100_u8)]
552pub struct ChannelFailure {
553 pub recipient_channel: u32,
555}