embedded_bacnet/network_protocol/
network_pdu.rs1use crate::{
2 application_protocol::application_pdu::ApplicationPdu,
3 common::{
4 error::Error,
5 io::{Reader, Writer},
6 },
7};
8
9#[derive(Debug, Clone)]
11#[cfg_attr(feature = "defmt", derive(defmt::Format))]
12pub struct NetworkPdu<'a> {
13 pub src: Option<SourceAddress>,
14 pub dst: Option<DestinationAddress>,
15 pub expect_reply: bool,
16 pub message_priority: MessagePriority,
17 pub network_message: NetworkMessage<'a>,
18}
19
20#[derive(Debug, Clone)]
22#[cfg_attr(feature = "defmt", derive(defmt::Format))]
23#[repr(u8)]
24pub enum MessagePriority {
25 Normal = 0,
26 Urgent = 1,
27 CriticalEquipment = 2,
28 LifeSafety = 3,
29}
30
31impl From<u8> for MessagePriority {
32 fn from(value: u8) -> Self {
33 const MASK: u8 = 0b0000_0011;
34 let value = value & MASK;
35
36 match value {
37 0 => MessagePriority::Normal,
38 1 => MessagePriority::Urgent,
39 2 => MessagePriority::CriticalEquipment,
40 3 => MessagePriority::LifeSafety,
41 _ => unreachable!(), }
43 }
44}
45
46#[derive(Debug, Clone)]
47#[cfg_attr(feature = "defmt", derive(defmt::Format))]
48#[repr(u8)]
49enum ControlFlags {
50 NetworkLayerMessage = 1 << 7,
51 HasDestination = 1 << 5,
52 HasSource = 1 << 3,
53 ExpectingReply = 1 << 2,
54}
55
56#[derive(Debug, Clone)]
57#[cfg_attr(feature = "defmt", derive(defmt::Format))]
58pub enum NetworkMessage<'a> {
59 Apdu(ApplicationPdu<'a>),
60 MessageType(MessageType),
61 CustomMessageType(u8),
62}
63
64#[derive(Debug, Clone)]
66#[cfg_attr(feature = "defmt", derive(defmt::Format))]
67#[repr(u8)]
68pub enum MessageType {
69 WhoIsRouterToNetwork = 0,
70 IAmRouterToNetwork = 1,
71 ICouldBeRouterToNetwork = 2,
72 RejectMessageToNetwork = 3,
73 RouterBusyToNetwork = 4,
74 RouterAvailableToNetwork = 5,
75 InitRtTable = 6,
76 InitRtTableAck = 7,
77 EstablishConnectionToNetwork = 8,
78 DisconnectConnectionToNetwork = 9,
79 ChallengeRequest = 10,
80 SecurityPayload = 11,
81 SecurityResponse = 12,
82 RequestKeyUpdate = 13,
83 UpdateKeySet = 14,
84 UpdateDistributionKey = 15,
85 RequestMasterKey = 16,
86 SetMasterKey = 17,
87 WhatIsNetworkNumber = 18,
88 NetworkNumberIs = 19,
89 }
92
93impl TryFrom<u8> for MessageType {
94 type Error = u8;
95
96 fn try_from(value: u8) -> Result<Self, Self::Error> {
97 match value {
98 0 => Ok(Self::WhoIsRouterToNetwork),
99 1 => Ok(Self::IAmRouterToNetwork),
100 2 => Ok(Self::ICouldBeRouterToNetwork),
101 3 => Ok(Self::RejectMessageToNetwork),
102 4 => Ok(Self::RouterBusyToNetwork),
103 5 => Ok(Self::RouterAvailableToNetwork),
104 6 => Ok(Self::InitRtTable),
105 7 => Ok(Self::InitRtTableAck),
106 8 => Ok(Self::EstablishConnectionToNetwork),
107 9 => Ok(Self::DisconnectConnectionToNetwork),
108 10 => Ok(Self::ChallengeRequest),
109 11 => Ok(Self::SecurityPayload),
110 12 => Ok(Self::SecurityResponse),
111 13 => Ok(Self::RequestKeyUpdate),
112 14 => Ok(Self::UpdateKeySet),
113 15 => Ok(Self::UpdateDistributionKey),
114 16 => Ok(Self::RequestMasterKey),
115 17 => Ok(Self::SetMasterKey),
116 18 => Ok(Self::WhatIsNetworkNumber),
117 19 => Ok(Self::NetworkNumberIs),
118 _ => Err(value),
119 }
120 }
121}
122
123impl<'a> NetworkPdu<'a> {
124 const VERSION: u8 = 0x01; pub fn new(
126 src: Option<SourceAddress>,
127 dst: Option<DestinationAddress>,
128 expect_reply: bool,
129 message_priority: MessagePriority,
130 message: NetworkMessage<'a>,
131 ) -> Self {
132 Self {
133 src,
134 dst,
135 expect_reply,
136 message_priority,
137 network_message: message,
138 }
139 }
140
141 pub fn encode(&self, writer: &mut Writer) {
142 writer.push(Self::VERSION);
143 writer.push(self.calculate_control());
144
145 if let Some(dst) = self.dst.as_ref() {
146 dst.network_address.encode(writer);
147 }
148
149 if let Some(src) = self.src.as_ref() {
150 src.encode(writer);
151 }
152
153 if let Some(dst) = self.dst.as_ref() {
155 writer.push(dst.hop_count);
156 }
157
158 match &self.network_message {
159 NetworkMessage::Apdu(adpu) => adpu.encode(writer),
160 NetworkMessage::MessageType(message_type) => {
161 writer.push(message_type.clone() as u8);
162 }
163 NetworkMessage::CustomMessageType(message_type) => {
164 writer.push(*message_type);
165 }
166 };
167 }
168
169 fn calculate_control(&self) -> u8 {
170 let is_network_layer_message = match &self.network_message {
171 NetworkMessage::Apdu(_) => 0,
172 NetworkMessage::MessageType(_) => ControlFlags::NetworkLayerMessage as u8,
173 NetworkMessage::CustomMessageType(_) => ControlFlags::NetworkLayerMessage as u8,
174 };
175
176 let has_destination = match self.dst.as_ref() {
177 Some(dst) => {
178 if dst.network_address.net > 0 {
179 ControlFlags::HasDestination as u8
180 } else {
181 0
182 }
183 }
184 None => 0,
185 };
186
187 let has_source = match self.src.as_ref() {
188 Some(src) => {
189 if src.net > 0 && src.net != 0xFFFF {
190 ControlFlags::HasSource as u8
191 } else {
192 0
193 }
194 }
195 None => 0,
196 };
197 let expecting_reply = if self.expect_reply {
198 ControlFlags::ExpectingReply as u8
199 } else {
200 0
201 };
202 let message_priority = self.message_priority.clone() as u8;
203
204 is_network_layer_message | has_destination | has_source | expecting_reply | message_priority
205 }
206
207 pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
208 let _version = reader.read_byte(buf)?;
210
211 let control = reader.read_byte(buf)?;
213 let has_dst = (control & ControlFlags::HasDestination as u8) > 0;
214 let has_src = (control & ControlFlags::HasSource as u8) > 0;
215 let is_network_message = (control & ControlFlags::NetworkLayerMessage as u8) > 0;
216 let expect_reply = (control & ControlFlags::ExpectingReply as u8) > 0;
217 let message_priority: MessagePriority = control.into();
218
219 let dst = if has_dst {
220 Some(NetworkAddress::decode(reader, buf)?)
221 } else {
222 None
223 };
224
225 let src = if has_src {
226 Some(NetworkAddress::decode(reader, buf)?)
227 } else {
228 None
229 };
230
231 let dst = if let Some(dst) = dst {
233 let hop_count = reader.read_byte(buf)?;
234 Some(DestinationAddress {
235 network_address: dst,
236 hop_count,
237 })
238 } else {
239 None
240 };
241
242 let network_message = if is_network_message {
243 let message_type = reader.read_byte(buf)?;
244 match message_type.try_into() {
245 Ok(message_type) => NetworkMessage::MessageType(message_type),
246 Err(custom_message_type) => NetworkMessage::CustomMessageType(custom_message_type),
247 }
248 } else {
249 let apdu = ApplicationPdu::decode(reader, buf)?;
250 NetworkMessage::Apdu(apdu)
251 };
252
253 Ok(Self {
254 dst,
255 src,
256 expect_reply,
257 message_priority,
258 network_message,
259 })
260 }
261}
262
263#[derive(Debug, Clone)]
264#[cfg_attr(feature = "defmt", derive(defmt::Format))]
265pub struct Addr {
266 pub ipv4: [u8; 4],
267 pub port: u16,
268}
269
270const IPV4_ADDR_LEN: u8 = 6;
271
272pub type SourceAddress = NetworkAddress;
273
274#[derive(Debug, Clone)]
275#[cfg_attr(feature = "defmt", derive(defmt::Format))]
276pub struct NetworkAddress {
277 pub net: u16,
278 pub addr: Option<Addr>,
279}
280
281#[derive(Debug, Clone)]
282#[cfg_attr(feature = "defmt", derive(defmt::Format))]
283pub struct DestinationAddress {
284 pub network_address: NetworkAddress,
285 pub hop_count: u8,
286}
287
288impl DestinationAddress {
289 pub fn new(net: u16, addr: Option<Addr>) -> Self {
290 Self {
291 network_address: NetworkAddress { net, addr },
292 hop_count: 255,
293 }
294 }
295}
296
297impl NetworkAddress {
298 pub fn encode(&self, writer: &mut Writer) {
299 writer.extend_from_slice(&self.net.to_be_bytes());
300 match self.addr.as_ref() {
301 Some(addr) => {
302 writer.push(IPV4_ADDR_LEN);
303 writer.extend_from_slice(&addr.ipv4);
304 writer.extend_from_slice(&addr.port.to_be_bytes());
305 }
306 None => writer.push(0),
307 }
308 }
309
310 pub fn decode(reader: &mut Reader, buf: &[u8]) -> Result<Self, Error> {
311 let net = u16::from_be_bytes(reader.read_bytes(buf)?);
312 let len = reader.read_byte(buf)?;
313 match len {
314 IPV4_ADDR_LEN => {
315 let ipv4: [u8; 4] = reader.read_bytes(buf)?;
316 let port = u16::from_be_bytes(reader.read_bytes(buf)?);
317
318 Ok(Self {
319 net,
320 addr: Some(Addr { ipv4, port }),
321 })
322 }
323 0 => Ok(Self { net, addr: None }),
324 x => Err(Error::Length((
325 "NetworkAddress decode ip len can only be 6 or 0",
326 x as u32,
327 ))),
328 }
329 }
330}