toe_beans/v4/message/options/
options.rs1use super::super::Slicer;
2use super::{
3 AddressListOption, AddressOption, FileOption, MaxMessage, MessageTypes, OpaqueOption,
4 OverloadOptions, SNameOption, StringOption, TimeOffset, TimeOption,
5};
6use log::trace;
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
14pub enum MessageOptions {
15 Pad,
17 Netmask(AddressOption),
19 TimeOffset(TimeOffset),
21 Router(AddressListOption),
23 DnsServer(AddressListOption),
25 HostName(StringOption),
28 DomainName(StringOption),
30 Broadcast(AddressOption),
32 RequestedIp(AddressOption),
36 LeaseTime(TimeOption),
42 Overload(OverloadOptions),
44 MessageType(MessageTypes),
46 ServerIdentifier(AddressOption),
48 RequestedOptions(Vec<u8>),
50 Message(StringOption),
52 MaxMessage(MaxMessage),
54 T1(TimeOption),
56 T2(TimeOption),
58 VendorId(OpaqueOption),
60 ClientId(OpaqueOption),
62 SName(SNameOption),
64 FileName(FileOption),
66 RapidCommit,
79 SubnetSelect(AddressOption),
81 End,
83 Other(u8, u8, Vec<u8>),
85}
86
87impl MessageOptions {
88 pub fn to_tag(&self) -> u8 {
91 match self {
92 Self::Pad => 0,
93 Self::Netmask(_) => 1,
94 Self::TimeOffset(_) => 2,
95 Self::Router(_) => 3,
96 Self::DnsServer(_) => 6,
97 Self::HostName(_) => 12,
98 Self::DomainName(_) => 15,
99 Self::Broadcast(_) => 28,
100 Self::RequestedIp(_) => 50,
101 Self::LeaseTime(_) => 51,
102 Self::Overload(_) => 52,
103 Self::MessageType(_) => 53,
104 Self::ServerIdentifier(_) => 54,
105 Self::RequestedOptions(_) => 55,
106 Self::Message(_) => 56,
107 Self::MaxMessage(_) => 57,
108 Self::T1(_) => 58,
109 Self::T2(_) => 59,
110 Self::VendorId(_) => 60,
111 Self::ClientId(_) => 61,
112 Self::SName(_) => 66,
113 Self::FileName(_) => 67,
114 Self::RapidCommit => 80,
115 Self::SubnetSelect(_) => 118,
116 Self::End => 255,
117 Self::Other(x, _, _) => *x,
118 }
119 }
120
121 fn from_tag_value(tag: u8, value: &[u8]) -> Self {
124 match tag {
125 1 => Self::Netmask(value.into()),
126 2 => Self::TimeOffset(value.into()),
127 3 => Self::Router(value.into()),
128 6 => Self::DnsServer(value.into()),
129 12 => Self::HostName(value.into()),
130 15 => Self::DomainName(value.into()),
131 28 => Self::Broadcast(value.into()),
132 50 => Self::RequestedIp(value.into()),
133 51 => Self::LeaseTime(value.into()),
134 52 => Self::Overload(value.into()),
135 53 => Self::MessageType(MessageTypes::from(value)),
136 54 => Self::ServerIdentifier(value.into()),
137 55 => Self::RequestedOptions(value.into()),
138 56 => Self::Message(value.into()),
139 57 => Self::MaxMessage(value.into()),
140 58 => Self::T1(value.into()),
141 59 => Self::T2(value.into()),
142 60 => Self::VendorId(value.into()),
143 61 => Self::ClientId(value.into()),
144 66 => Self::SName(value.into()),
145 67 => Self::FileName(value.into()),
146 118 => Self::SubnetSelect(value.into()),
147 _ => Self::Other(tag, value.len() as u8, value.into()),
148 }
149 }
150
151 #[inline]
153 pub fn extend_into(&self, bytes: &mut Vec<u8>) {
154 match self {
155 Self::Pad => bytes.push(0),
156 Self::End => bytes.push(255),
157 Self::RapidCommit => bytes.push(80),
158 Self::LeaseTime(x) => x.extend_into(bytes, 51),
159 Self::T1(x) => x.extend_into(bytes, 58),
160 Self::T2(x) => x.extend_into(bytes, 59),
161 Self::RequestedIp(x) => x.extend_into(bytes, 50),
162 Self::ServerIdentifier(x) => x.extend_into(bytes, 54),
163 Self::MessageType(x) => x.extend_into(bytes, 53),
164 Self::Netmask(x) => x.extend_into(bytes, 1),
165 Self::Broadcast(x) => x.extend_into(bytes, 28),
166 Self::Overload(x) => x.extend_into(bytes, 52),
167 Self::SName(x) => x.extend_into(bytes, 66),
168 Self::FileName(x) => x.extend_into(bytes, 67),
169 Self::Router(x) => x.extend_into(bytes, 3),
170 Self::DnsServer(x) => x.extend_into(bytes, 6),
171 Self::MaxMessage(x) => x.extend_into(bytes, 57),
172 Self::HostName(x) => x.extend_into(bytes, 12),
173 Self::DomainName(x) => x.extend_into(bytes, 15),
174 Self::Message(x) => x.extend_into(bytes, 56),
175 Self::SubnetSelect(x) => x.extend_into(bytes, 118),
176 Self::VendorId(x) => x.extend_into(bytes, 60),
177 Self::ClientId(x) => x.extend_into(bytes, 61),
178 Self::TimeOffset(x) => x.extend_into(bytes, 2),
179
180 Self::RequestedOptions(v) => {
181 bytes.push(55);
182 bytes.push(v.len() as u8);
183 bytes.extend(v.iter());
184 }
185
186 Self::Other(t, l, v) => {
187 bytes.push(*t);
188 bytes.push(*l);
189 bytes.extend(v);
190 }
191 };
192 }
193
194 pub fn from_bytes(bytes: &[u8]) -> Vec<Self> {
196 let mut slicer = Slicer::new(bytes);
197 let mut options: Vec<MessageOptions> = Vec::with_capacity(308);
198
199 while let Some(tag) = slicer.parse(1) {
201 trace!("parsing option {:?}", tag);
202 match tag[0] {
203 0 => {} 80 => {
205 options.push(Self::RapidCommit);
206 }
207 255 => {
208 options.push(Self::End);
210 break; }
212 tag_with_length => {
213 match slicer.parse(1) {
215 Some(length) => match slicer.parse(length[0] as usize) {
216 Some(value) => {
217 options.push(MessageOptions::from_tag_value(tag_with_length, value))
218 }
219 None => break, },
221 None => break, }
223 }
224 }
225 }
226
227 options
228 }
229}