bacnet_objects/network_port/bip6_config.rs
1//! Declared configuration for an unbound application-level B/IPv6 port
2//! (Annex U). As for B/IP, the mode is not configuration: a registered
3//! owner publishes it, with its actual bind.
4
5use crate::common;
6use crate::prelude::*;
7use bacnet_types::error::Error;
8
9/// FF05::BAC0, the site-local BACnet group a B/IPv6 transport broadcasts to
10/// by default (Annex U.4).
11const SITE_LOCAL_GROUP: [u8; 16] = [0xFF, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xBA, 0xC0];
12
13/// Complete configured B/IPv6 snapshot. Fixed-size addresses prevent
14/// malformed IPv6 values. The unspecified address `::` for the address,
15/// gateway or one DNS server means unknown or unconfigured; none of them
16/// describes an observed interface or route.
17///
18/// The object serves this as a port whose addresses are configured by hand:
19/// it lists no IPv6_Auto_Addressing_Enable (Table 12-71 footnote 16) or
20/// IPv6_Zone_Index (footnote 17) row, nor the optional DHCPv6 rows, and
21/// every row is read-only over BACnet.
22///
23/// `vmac`, and the UDP port the multicast row carries, are placeholders
24/// until a registered owner publishes the VMAC it uses and the port it is
25/// bound to.
26#[derive(Clone, Debug, PartialEq, Eq)]
27pub struct Bip6PortConfig {
28 /// Caller-configured number; zero means unknown, 65535 is invalid.
29 pub network_number: u16,
30 /// Port APDU_Length, independent of Device Max_APDU_Length_Accepted;
31 /// at least 50.
32 pub apdu_length: u32,
33 /// Configured IPv6 address, most significant octet first: IPv6_Address.
34 pub ip_address: [u8; 16],
35 /// The subnet prefix length of `ip_address`, 1 to 128:
36 /// IPv6_Prefix_Length.
37 pub prefix_length: u8,
38 /// BACnet_IPv6_UDP_Port. Zero is allowed in this unbound configuration.
39 pub udp_port: u16,
40 /// Configured gateway, with no assumed OS route: IPv6_Default_Gateway.
41 pub default_gateway: [u8; 16],
42 /// At least one address; `::` represents unavailable DNS:
43 /// IPv6_DNS_Server.
44 pub dns_servers: Vec<[u8; 16]>,
45 /// The multicast group the port broadcasts to. BACnet_IPv6_Multicast_Address
46 /// serves it followed by the port's UDP port, since the transport sends
47 /// its broadcasts to the group at its own port.
48 pub multicast_address: [u8; 16],
49 /// The port's 3-octet VMAC (Annex U.1.3): MAC_Address. A registered
50 /// owner publishes the VMAC it actually uses, which replaces this one.
51 pub vmac: [u8; 3],
52}
53
54impl Default for Bip6PortConfig {
55 fn default() -> Self {
56 Self {
57 network_number: 0,
58 // Declared B/IPv6 capacity of this library's transport profile.
59 apdu_length: 1476,
60 ip_address: [0; 16],
61 prefix_length: 64,
62 udp_port: 47808,
63 default_gateway: [0; 16],
64 dns_servers: vec![[0; 16]],
65 multicast_address: SITE_LOCAL_GROUP,
66 vmac: [0; 3],
67 }
68 }
69}
70
71impl Bip6PortConfig {
72 pub(super) fn validate(&self, instance: u32) -> Result<(), Error> {
73 // The flat application profile's local Port ID policy, as for B/IP;
74 // a prefix length is 1 to 128 (Clause 12.56.41); a broadcast group
75 // is an IPv6 multicast address (Annex U.4); an IPv4-mapped address
76 // is an IPv4 port, which `new_bip` describes.
77 if !(1..=255).contains(&instance)
78 || core::net::Ipv6Addr::from(self.ip_address)
79 .to_ipv4_mapped()
80 .is_some()
81 || self.network_number == u16::MAX
82 || self.apdu_length < 50
83 || self.dns_servers.is_empty()
84 || !(1..=128).contains(&self.prefix_length)
85 || self.multicast_address[0] != 0xFF
86 {
87 return Err(common::value_out_of_range_error());
88 }
89 Ok(())
90 }
91
92 /// BACnet_IPv6_Multicast_Address: the group, then the UDP port, each
93 /// most significant octet first (Clause 12.56.44).
94 pub(super) fn multicast_with_port(&self) -> Vec<u8> {
95 let mut value = self.multicast_address.to_vec();
96 value.extend_from_slice(&self.udp_port.to_be_bytes());
97 value
98 }
99}
100
101/// What a started B/IPv6 owner publishes for its registered Network Port:
102/// the address and UDP port it is bound to, the VMAC it uses and the group
103/// it broadcasts to.
104#[derive(Clone, Copy, Debug, PartialEq, Eq)]
105pub(crate) struct Bip6Bind {
106 /// The bound IPv6 address, most significant octet first.
107 pub ip: [u8; 16],
108 /// The bound UDP port, never zero.
109 pub udp: u16,
110 /// The VMAC the owner uses (Annex U.1.3).
111 pub vmac: [u8; 3],
112 /// The multicast group its broadcasts go to.
113 pub multicast: [u8; 16],
114}