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