ipmi_rs/connection/impls/rmcp/v2_0/messages/
rakp_2.rs1use std::num::NonZeroU32;
2
3use super::RakpErrorStatusCode;
4
5#[derive(Debug)]
6pub enum ParseError {
7 NotEnoughData,
8 ErrorStatusCode(ErrorStatusCode),
9 UnknownErrorStatusCode(u8),
10 InvalidRemoteConsoleSessionId,
11}
12
13#[derive(Debug, PartialEq)]
14pub struct RakpMessage2<'a> {
15 pub message_tag: u8,
16 pub remote_console_session_id: NonZeroU32,
17 pub managed_system_random_number: [u8; 16],
18 pub managed_system_guid: [u8; 16],
19 pub key_exchange_auth_code: &'a [u8],
20}
21
22impl<'a> RakpMessage2<'a> {
23 pub fn from_data(data: &'a [u8]) -> Result<Self, ParseError> {
24 if data.len() < 4 {
26 return Err(ParseError::NotEnoughData);
27 }
28
29 let message_tag = data[0];
30 let status_code = data[2];
31
32 if status_code != 0 {
33 return Err(ErrorStatusCode::try_from(status_code)
34 .map(ParseError::ErrorStatusCode)
35 .unwrap_or(ParseError::UnknownErrorStatusCode(status_code)));
36 }
37
38 if data.len() < 40 {
39 return Err(ParseError::NotEnoughData);
40 }
41
42 let remote_console_session_id =
43 if let Some(v) = NonZeroU32::new(u32::from_le_bytes(data[4..8].try_into().unwrap())) {
44 v
45 } else {
46 return Err(ParseError::InvalidRemoteConsoleSessionId);
47 };
48
49 let managed_system_random_number = data[8..24].try_into().unwrap();
50 let managed_system_guid = data[24..40].try_into().unwrap();
51 let key_exchange_auth_code = &data[40..];
52
53 Ok(Self {
54 message_tag,
55 remote_console_session_id,
56 managed_system_random_number,
57 managed_system_guid,
58 key_exchange_auth_code,
59 })
60 }
61}
62
63#[derive(Debug, Clone, Copy, PartialEq)]
64#[repr(u8)]
65pub enum ErrorStatusCode {
66 Common(RakpErrorStatusCode),
67 InactiveSessionId = 0x08,
68 InvalidRole = 0x09,
69 UnauthorizedRoleOrPrivilegeLevelRequested = 0x0A,
70 InsufficientResourcesToCreateSessionAtRequestedRole = 0x0B,
71 InvalidNameLength = 0x0C,
72 UnauthorizedName = 0x0D,
73}
74
75impl TryFrom<u8> for ErrorStatusCode {
76 type Error = ();
77
78 fn try_from(value: u8) -> Result<Self, Self::Error> {
79 if let Ok(common) = TryFrom::try_from(value) {
80 return Ok(ErrorStatusCode::Common(common));
81 }
82
83 let value = match value {
84 0x03 => ErrorStatusCode::InactiveSessionId,
85 0x09 => ErrorStatusCode::InvalidRole,
86 0x0A => ErrorStatusCode::UnauthorizedRoleOrPrivilegeLevelRequested,
87 0x0B => ErrorStatusCode::InsufficientResourcesToCreateSessionAtRequestedRole,
88 0x0C => ErrorStatusCode::InvalidNameLength,
89 0x0D => ErrorStatusCode::UnauthorizedName,
90 _ => return Err(()),
91 };
92
93 Ok(value)
94 }
95}
96
97#[test]
98pub fn from_data() {
99 let data = [
100 0x00, 0x00, 0x00, 0x00, 0xa4, 0xa3, 0xa2, 0xa0, 0xe8, 0x2c, 0x00, 0x00, 0x42, 0x72, 0x00,
101 0x00, 0x59, 0x18, 0x00, 0x00, 0xac, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x61, 0xba, 0x25, 0xc8,
103 0x22, 0x4e, 0x32, 0x78, 0x63, 0x62, 0x6b, 0x30, 0x7c, 0x8d, 0xc8, 0x15, 0x22, 0x90, 0x91,
104 ];
105
106 let message = RakpMessage2::from_data(&data).unwrap();
107
108 let expected = RakpMessage2 {
109 message_tag: 0x00,
110 remote_console_session_id: NonZeroU32::new(0xa0a2a3a4).unwrap(),
111 managed_system_random_number: [
112 0xe8, 0x2c, 0x00, 0x00, 0x42, 0x72, 0x00, 0x00, 0x59, 0x18, 0x00, 0x00, 0xac, 0x04,
113 0x00, 0x00,
114 ],
115 managed_system_guid: [
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117 0x00, 0x00,
118 ],
119 key_exchange_auth_code: &[
120 0x6b, 0x61, 0xba, 0x25, 0xc8, 0x22, 0x4e, 0x32, 0x78, 0x63, 0x62, 0x6b, 0x30, 0x7c,
121 0x8d, 0xc8, 0x15, 0x22, 0x90, 0x91,
122 ],
123 };
124
125 assert_eq!(expected, message);
126}