1use crate::comm::BytesWrap;
2use crate::packet::ident_resp::PacketIdentResp;
3use anyhow::{bail, Result};
4use std::fmt::{Debug, Formatter};
5use std::net::Ipv4Addr;
6
7#[derive(Debug, Eq, PartialEq, Clone)]
13pub enum BlockInfo {
14 Reserved,
15 UnSupport([u8; 2]),
16}
17impl BlockInfo {
18 pub fn to_u8_array(&self) -> [u8; 2] {
19 match self {
20 Self::Reserved => [0x00, 0x00],
21 Self::UnSupport(a) => a.clone(),
22 }
23 }
24}
25
26impl TryFrom<BytesWrap> for BlockInfo {
27 type Error = anyhow::Error;
28
29 fn try_from(value: BytesWrap) -> std::result::Result<Self, Self::Error> {
30 let val = value.slice(0..=1)?;
31 let data = [val.as_ref()[0], val.as_ref()[1]];
32 Ok(match data {
33 RESERVED => Self::Reserved,
34 data => Self::UnSupport(data),
35 })
36 }
37}
38
39const RESERVED: [u8; 2] = [0x00, 0x00];
40const USE_TEMPORARY: [u8; 2] = [0x00, 0x00];
41const SAVE_PERMANENT: [u8; 2] = [0x00, 0x01];
42#[derive(Eq, PartialEq, Clone)]
43pub enum BlockQualifier {
44 UseTemporary,
45 SavePermanent,
46 UnSupport([u8; 2]),
47}
48impl BlockQualifier {
49 pub fn to_u8_array(&self) -> [u8; 2] {
50 match self {
51 Self::UnSupport(a) => a.clone(),
52 Self::UseTemporary => USE_TEMPORARY,
53 Self::SavePermanent => SAVE_PERMANENT,
54 }
55 }
56}
57impl Debug for BlockQualifier {
58 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
59 match self {
60 Self::UseTemporary => {
61 write!(f, "Use the value temporary")
62 }
63 Self::SavePermanent => {
64 write!(f, "Save the value permanent")
65 }
66 Self::UnSupport(a) => {
67 write!(f, "UnSupport value {:?}", a)
68 }
69 }
70 }
71}
72impl TryFrom<BytesWrap> for BlockQualifier {
73 type Error = anyhow::Error;
74
75 fn try_from(value: BytesWrap) -> std::result::Result<Self, Self::Error> {
76 let val = value.slice(0..=1)?;
77 let a = [val.as_ref()[0], val.as_ref()[1]];
78 Ok(match a {
79 USE_TEMPORARY => Self::UseTemporary,
80 SAVE_PERMANENT => Self::SavePermanent,
81 b => Self::UnSupport(b),
82 })
83 }
84}
85#[derive(Debug, Eq, PartialEq, Clone)]
86pub struct InnerIpAddr(pub Ipv4Addr, pub Ipv4Addr, pub Ipv4Addr);
87impl InnerIpAddr {
88 pub fn new(data: BytesWrap) -> Result<Self> {
89 let val = data.slice(0..=11)?;
90 let val = val.as_ref();
91 Ok(Self(
92 Ipv4Addr::new(val[0], val[1], val[2], val[3]),
93 Ipv4Addr::new(val[4], val[5], val[6], val[7]),
94 Ipv4Addr::new(val[8], val[9], val[10], val[11]),
95 ))
96 }
97 pub fn new_by_ipv4(ip: Ipv4Addr, subnetmask: Ipv4Addr, gateway: Ipv4Addr) -> Self {
98 Self(ip, subnetmask, gateway)
99 }
100 pub fn append_value_to_data(&self, data: &mut Vec<u8>) {
101 data.extend_from_slice(self.0.octets().as_slice());
102 data.extend_from_slice(self.1.octets().as_slice());
103 data.extend_from_slice(self.2.octets().as_slice());
104 }
105 pub fn payload_size(&self) -> usize {
106 12
107 }
108 pub fn to_option(self) -> OptionAndSubValue {
109 OptionAndSubValue::IpAddr(self)
110 }
111
112 pub fn append_to_ident_resp(self, packet: &mut PacketIdentResp, info: IpBlockInfo) {
113 packet.append_block_ip(self, info)
114 }
115}
116
117#[derive(Debug, Eq, PartialEq, Clone)]
118pub struct Response(pub OptionAndSub, pub BlockError);
119impl Response {
120 pub fn len(&self) -> usize {
121 5
122 }
123 pub fn payload(&self) -> u16 {
124 3
125 }
126 pub fn append_value_to_data(&self, data: &mut Vec<u8>) {
127 data.extend_from_slice(self.0.to_u8_array().as_slice());
128 data.push(self.1 as u8);
129 }
130 pub fn to_option(self) -> OptionAndSubValue {
131 OptionAndSubValue::Response(self)
132 }
133}
134
135impl TryFrom<BytesWrap> for Response {
136 type Error = anyhow::Error;
137 fn try_from(data: BytesWrap) -> Result<Self, Self::Error> {
138 let val = data.slice(0..=2)?;
139 let ref_u8 = val.as_ref();
140 Ok(Self(
141 OptionAndSub::try_from(val.clone())?,
142 BlockError::try_from(ref_u8[2])?,
143 ))
144 }
145}
146
147#[derive(Default)]
148pub struct DeviceOptionsBuilder(Vec<OptionAndSub>);
149
150impl DeviceOptionsBuilder {
151 pub fn append_option(mut self, option: OptionAndSub) -> Self {
152 self.0.push(option);
153 self
154 }
155 pub fn build(self) -> OptionAndSubValue {
156 OptionAndSubValue::DeviceOptions(self.0)
157 }
158}
159
160#[derive(Debug, Eq, PartialEq, Clone)]
161pub enum OptionAndSubValue {
162 IpAddr(InnerIpAddr),
164 ManufacturerSpecific(BytesWrap),
166 NameOfStation(BytesWrap),
167 DeviceId([u8; 2], [u8; 2]),
168 DeviceRole(u8, u8), DeviceOptions(Vec<OptionAndSub>),
170 Response(Response), All,
178 Other(OptionAndSub, BytesWrap),
181}
182
183impl OptionAndSubValue {
184 pub fn append_option_to_data(&self, data: &mut Vec<u8>) {
185 match self {
186 Self::IpAddr(_) => {
187 data.extend_from_slice(OptionAndSub::IpAddr.to_u8_array().as_slice())
188 }
189 Self::ManufacturerSpecific(_) => {
191 data.extend_from_slice(OptionAndSub::ManufacturerSpecific.to_u8_array().as_slice())
192 }
193 Self::NameOfStation(_) => {
194 data.extend_from_slice(OptionAndSub::NameOfStation.to_u8_array().as_slice())
195 }
196 Self::DeviceId(_, _) => {
197 data.extend_from_slice(OptionAndSub::DeviceId.to_u8_array().as_slice())
198 }
199 Self::DeviceRole(_, _) => {
200 data.extend_from_slice(OptionAndSub::DeviceRole.to_u8_array().as_slice())
201 }
202 Self::DeviceOptions(_) => {
203 data.extend_from_slice(OptionAndSub::DeviceOptions.to_u8_array().as_slice())
204 }
205 Self::Response(_) => {
206 data.extend_from_slice(OptionAndSub::Response.to_u8_array().as_slice())
207 }
208 Self::All => {
209 data.extend_from_slice(OptionAndSub::All.to_u8_array().as_slice())
210 }
211 Self::Other(a, _) => {
212 data.extend_from_slice(a.to_u8_array().as_slice())
213 }
214 }
215 }
216 pub fn append_value_to_data(&self, data: &mut Vec<u8>) {
217 match self {
218 Self::IpAddr(a) => {
219 data.extend_from_slice(a.0.octets().as_slice());
220 data.extend_from_slice(a.1.octets().as_slice());
221 data.extend_from_slice(a.2.octets().as_slice());
222 }
223 Self::ManufacturerSpecific(val) => {
225 data.extend_from_slice(val.as_ref());
226 }
227 Self::NameOfStation(val) => {
228 data.extend_from_slice(val.as_ref());
229 }
230 Self::DeviceId(a, b) => {
231 data.extend_from_slice(a.as_ref());
232 data.extend_from_slice(b.as_ref());
233 }
234 Self::DeviceRole(a, b) => {
235 data.push(*a);
236 data.push(*b);
237 }
238 Self::DeviceOptions(val) => {
239 for option in val {
240 data.extend_from_slice(option.to_u8_array().as_slice());
241 }
242 }
243 Self::Response(a) => {
244 a.append_value_to_data(data);
245 }
246 Self::All => {
247 }
248 Self::Other(_, a) => {
249 data.extend_from_slice(a.as_ref())
250 }
251 }
252 }
253 pub fn init_by_ty(ty: OptionAndSub, data: BytesWrap) -> Result<Self> {
255 Ok(match ty {
256 OptionAndSub::IpAddr => {
257 let val = data.slice(0..=11)?;
258 let val = val.as_ref();
259 Self::IpAddr(InnerIpAddr(
260 Ipv4Addr::new(val[0], val[1], val[2], val[3]),
261 Ipv4Addr::new(val[4], val[5], val[6], val[7]),
262 Ipv4Addr::new(val[8], val[9], val[10], val[11]),
263 ))
264 }
265 OptionAndSub::ManufacturerSpecific => Self::ManufacturerSpecific(data),
266 OptionAndSub::NameOfStation => Self::NameOfStation(data),
267 OptionAndSub::DeviceId => {
268 let val = data.slice(0..=3)?;
269 let val = val.as_ref();
270 Self::DeviceId([val[0], val[1]], [val[2], val[3]])
271 }
272 OptionAndSub::DeviceRole => {
273 let val = data.slice(0..=1)?;
274 let val = val.as_ref();
275 Self::DeviceRole(val[0], val[1])
276 }
277 OptionAndSub::DeviceOptions => {
278 let mut index = 0;
279 let mut options = Vec::new();
280 while let Ok(val) = data.slice(index..) {
281 if val.len() == 0 {
282 break;
283 }
284 options.push(OptionAndSub::try_from(val)?);
285 index += 2;
286 }
287 Self::DeviceOptions(options)
288 }
289 OptionAndSub::Response => {
290 let val = data.slice(0..=2)?;
291 Self::Response(Response::try_from(val)?)
292 }
293 OptionAndSub::All => {
294 Self::All
295 }
296 option => {
297 Self::Other(option, data)
298 }
299 })
300 }
301 pub fn payload_size(&self) -> usize {
302 match self {
303 Self::IpAddr(_) => 12,
304 Self::ManufacturerSpecific(val) => val.len(),
306 Self::NameOfStation(val) => val.len(),
307 Self::DeviceId(_, _) => 4,
308 Self::DeviceRole(_, _) => 2,
309 Self::DeviceOptions(val) => val.len() * 2,
310 Self::Response(_) => 3,
311 Self::All => 0,
312 Self::Other(_, a) => a.len(),
313 }
314 }
315
316 pub fn append_to_ident_resp_default(self, packet: &mut PacketIdentResp) {
317 packet.append_block_common_default(self);
318 }
319 pub fn append_to_ident_resp(self, packet: &mut PacketIdentResp, info: BlockInfo) {
320 packet.append_block_common(self, info);
321 }
322}
323
324#[derive(Debug, Clone, Copy, Eq, PartialEq)]
325pub enum OptionAndSub {
326 MarAddr,
327 IpAddr,
328 FullIpSuite,
329 ManufacturerSpecific,
330 NameOfStation,
331 DeviceId,
332 DeviceRole,
333 DeviceOptions,
334 AliasName,
335 StartTransaction,
336 EndTransaction,
337 Signal,
338 Response,
339 ResetFactory,
340 DevicecInitiative,
341 All,
342 DHCP(u8),
343 LLDP(u8),
344 Other(u8, u8),
345}
346
347impl TryFrom<BytesWrap> for OptionAndSub {
348 type Error = anyhow::Error;
349
350 fn try_from(value: BytesWrap) -> std::result::Result<Self, Self::Error> {
351 if let Some(a) = value.as_ref().get(0..=1) {
352 OptionAndSub::new(a[0], a[1])
353 } else {
354 bail!("todo: {:?}", value);
355 }
356 }
357}
358
359impl OptionAndSub {
360 pub fn new(b: u8, c: u8) -> Result<Self> {
361 let a = (b, c);
362 Ok(match a {
363 (1, 1) => Self::MarAddr,
364 (1, 2) => Self::IpAddr,
365 (1, 3) => Self::FullIpSuite,
366 (2, 1) => Self::ManufacturerSpecific,
367 (2, 2) => Self::NameOfStation,
368 (2, 3) => Self::DeviceId,
369 (2, 4) => Self::DeviceRole,
370 (2, 5) => Self::DeviceOptions,
371 (2, 6) => Self::AliasName,
372 (5, 1) => Self::StartTransaction,
373 (5, 2) => Self::EndTransaction,
374 (5, 3) => Self::Signal,
375 (5, 4) => Self::Response,
376 (5, 6) => Self::ResetFactory,
377 (6, 1) => Self::DevicecInitiative,
378 (255, 255) => Self::All,
379 (3, a) => Self::DHCP(a),
380 (4, a) => Self::LLDP(a),
381 (a, b) => Self::Other(a, b),
382 })
383 }
384 pub fn to_u8s(&self) -> (u8, u8) {
385 match *self {
386 Self::MarAddr => (1, 1),
387 Self::IpAddr => (1, 2),
388 Self::FullIpSuite => (1, 3),
389 Self::ManufacturerSpecific => (2, 1),
390 Self::NameOfStation => (2, 2),
391 Self::DeviceId => (2, 3),
392 Self::DeviceRole => (2, 4),
393 Self::DeviceOptions => (2, 5),
394 Self::AliasName => (2, 6),
395 Self::StartTransaction => (5, 1),
396 Self::EndTransaction => (5, 2),
397 Self::Signal => (5, 3),
398 Self::Response => (5, 4),
399 Self::ResetFactory => (5, 6),
400 Self::DevicecInitiative => (6, 1),
401 Self::All => (255, 255),
402 Self::DHCP(a) => (3, a),
403 Self::LLDP(a) => (4, a),
404 Self::Other(a, b) => (a, b),
405 }
406 }
407 #[inline]
408 pub fn to_u8_array(&self) -> [u8; 2] {
409 match *self {
410 Self::MarAddr => [1, 1],
411 Self::IpAddr => [1, 2],
412 Self::FullIpSuite => [1, 3],
413 Self::ManufacturerSpecific => [2, 1],
414 Self::NameOfStation => [2, 2],
415 Self::DeviceId => [2, 3],
416 Self::DeviceRole => [2, 4],
417 Self::DeviceOptions => [2, 5],
418 Self::AliasName => [2, 6],
419 Self::StartTransaction => [5, 1],
420 Self::EndTransaction => [5, 2],
421 Self::Signal => [5, 3],
422 Self::Response => [5, 4],
423 Self::ResetFactory => [5, 6],
424 Self::DevicecInitiative => [6, 1],
425 Self::All => [255, 255],
426 Self::DHCP(a) => [3, a],
427 Self::LLDP(a) => [4, a],
428 Self::Other(a, b) => [a, b],
429 }
430 }
431}
432#[derive(Debug, Copy, Clone, Eq, PartialEq)]
433#[repr(u8)]
434pub enum BlockError {
435 Ok = 0x00,
436 OptionUnsupp = 0x01,
437 SuboptionUnsuppOrNoDataSetAvail = 0x02,
438 SuboptionNotSet = 0x03,
439 ResourceError = 0x04,
440 SETNotPossibleByLocalReasons = 0x05,
441 InOoperationSETNotPossible = 0x06,
442}
443
444impl TryFrom<u8> for BlockError {
445 type Error = anyhow::Error;
446
447 fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
448 Ok(match value {
449 0x00 => Self::Ok,
450 0x01 => Self::OptionUnsupp,
451 0x02 => Self::SuboptionUnsuppOrNoDataSetAvail,
452 0x03 => Self::SuboptionNotSet,
453 0x04 => Self::ResourceError,
454 0x05 => Self::SETNotPossibleByLocalReasons,
455 0x06 => Self::InOoperationSETNotPossible,
456 a => bail!("unsupport block error: {}", a),
457 })
458 }
459}
460
461#[derive(Debug, Eq, PartialEq, Copy, Clone)]
462pub enum IpBlockInfo {
463 IpNotSet,
464 IpSet,
465 IpSetByDhcp,
466 IpNotSetConflict,
467 IpSetConflict,
468 IpSetByDhcpConflict,
469 UnSupport([u8; 2]),
470}
471
472impl Default for IpBlockInfo {
473 fn default() -> Self {
474 Self::IpSet
475 }
476}
477
478impl IpBlockInfo {
479 pub fn to_u8_array(&self) -> [u8; 2] {
480 match self {
481 Self::IpNotSet => [0x00, 0x00],
482 Self::IpSet => [0x00, 0x01],
483 Self::IpSetByDhcp => [0x00, 0x02],
484 Self::IpNotSetConflict => [0x00, 0x80],
485 Self::IpSetConflict => [0x00, 0x81],
486 Self::IpSetByDhcpConflict => [0x00, 0x82],
487 Self::UnSupport(data) => data.clone(),
488 }
489 }
490}
491
492impl TryFrom<BytesWrap> for IpBlockInfo {
493 type Error = anyhow::Error;
494 fn try_from(value: BytesWrap) -> Result<Self, Self::Error> {
495 let val = value.slice(0..=1)?;
496 let data = [val.as_ref()[0], val.as_ref()[1]];
497 Ok(match data {
498 [0x00, 0x00] => Self::IpNotSet,
499 [0x00, 0x01] => Self::IpSet,
500 [0x00, 0x02] => Self::IpSetByDhcp,
501 [0x00, 0x80] => Self::IpNotSetConflict,
502 [0x00, 0x81] => Self::IpSetConflict,
503 [0x00, 0x82] => Self::IpSetByDhcpConflict,
504 data => Self::UnSupport(data),
505 })
506 }
507}