UNPKG

zigbee-on-host

Version:

Zigbee stack designed to run on a host and communicate with a radio co-processor (RCP)

556 lines (555 loc) 30.2 kB
import { type MACHeader } from "../zigbee/mac.js"; import { type ZigbeeSecurityHeader } from "../zigbee/zigbee.js"; import { ZigbeeAPSCommandId, ZigbeeAPSDeliveryMode, type ZigbeeAPSHeader } from "../zigbee/zigbee-aps.js"; import { type ZigbeeNWKHeader, ZigbeeNWKRouteDiscovery } from "../zigbee/zigbee-nwk.js"; import type { MACHandler } from "./mac-handler.js"; import { type NWKHandler } from "./nwk-handler.js"; import { type StackCallbacks, type StackContext } from "./stack-context.js"; /** * Callbacks for APS handler to communicate with driver */ export interface APSHandlerCallbacks { onFrame: StackCallbacks["onFrame"]; onDeviceJoined: StackCallbacks["onDeviceJoined"]; onDeviceRejoined: StackCallbacks["onDeviceRejoined"]; onDeviceAuthorized: StackCallbacks["onDeviceAuthorized"]; } /** apsAckWaitDuration: Default ack wait duration per Zigbee 3.0 spec (milliseconds). */ export declare const CONFIG_APS_ACK_WAIT_DURATION_MS: number; /** apsMaxFrameRetries: Default number of APS retransmissions when ACK is missing. */ export declare const CONFIG_APS_MAX_FRAME_RETRIES = 3; /** * APS Handler - Zigbee Application Support Layer Operations */ export declare class APSHandler { #private; constructor(context: StackContext, macHandler: MACHandler, nwkHandler: NWKHandler, callbacks: APSHandlerCallbacks); start(): Promise<void>; stop(): void; /** * Get next APS counter. * HOT PATH: Optimized counter increment * @returns Incremented APS counter (wraps at 255) */ nextCounter(): number; /** * Get next ZDO sequence number. * HOT PATH: Optimized counter increment * @returns Incremented ZDO sequence number (wraps at 255) */ nextZDOSeqNum(): number; /** * 05-3474-23 #2.2.6.5 (APS duplicate rejection) * * Check whether an incoming APS frame is a duplicate and update the duplicate table accordingly. * * SPEC COMPLIANCE NOTES: * - ✅ Uses {src64, dstEndpoint, clusterId, apsCounter} tuple per spec to detect duplicates * - ✅ Applies configurable timeout window (DEFAULT ≈ 8s) after which entries expire * - ✅ Tracks fragment block numbers explicitly so out-of-order fragment retransmissions are accepted * - ✅ Drops duplicates before generating APS ACKs, matching required ordering * - ⚠️ Duplicate table stored in-memory only; persistence across restart is not implemented * DEVICE SCOPE: Coordinator, routers (N/A), end devices (N/A) * * @returns true when the frame was already seen within the duplicate removal timeout. */ isDuplicateFrame(nwkHeader: ZigbeeNWKHeader, apsHeader: ZigbeeAPSHeader, now?: number): boolean; /** * 05-3474-23 #4.4.1 (APS data service) * * Send a Zigbee APS DATA frame and track pending ACK if necessary. * * SPEC COMPLIANCE NOTES: * - ✅ Builds APS frame with ackRequest flag and delivery mode per parameters * - ✅ Tracks pending acknowledgements per spec timeout (CONFIG_APS_ACK_WAIT_DURATION_MS ≈ 1.5s) * - ✅ Applies fragmentation when payload exceeds APS maximum (CONFIG_APS_UNFRAGMENTED_PAYLOAD_MAX) * - ⚠️ Fragment reassembly timer configurable but not spec-driven (CONFIG_APS_FRAGMENT_REASSEMBLY_TIMEOUT_MS) * - ⚠️ Route discovery hint (nwkDiscoverRoute) passed to NWK handler without additional validation * DEVICE SCOPE: Coordinator, routers (N/A), end devices (N/A) * * @param finalPayload Encoded APS payload * @param nwkDiscoverRoute NWK discovery mode * @param nwkDest16 Destination short address (if known) * @param nwkDest64 Destination IEEE (optional) * @param apsDeliveryMode Delivery mode (unicast/group/broadcast) * @param clusterId Cluster identifier * @param profileId Profile identifier * @param destEndpoint Destination endpoint * @param sourceEndpoint Source endpoint * @param group Group identifier (when group addressed) * @returns The APS counter of the sent frame */ sendData(finalPayload: Buffer, nwkDiscoverRoute: ZigbeeNWKRouteDiscovery, nwkDest16: number | undefined, nwkDest64: bigint | undefined, apsDeliveryMode: ZigbeeAPSDeliveryMode, clusterId: number, profileId: number, destEndpoint: number | undefined, sourceEndpoint: number | undefined, group: number | undefined): Promise<number>; /** * 05-3474-23 #4.4.2.3 (APS acknowledgement) * * SPEC COMPLIANCE NOTES: * - ✅ Mirrors counter and cluster metadata per spec Table 4-10 * - ✅ Selects unicast delivery mode and suppresses retransmit (ackRequest=false) * - ✅ Reuses NWK/MAC sequence numbers from incoming frame to satisfy reliability requirements * - ⚠️ Fragment ACK format limited to simple bitfield (supports first block only) * - ⚠️ Does not retry failed acknowledgements; relies on NWK retransmissions * DEVICE SCOPE: Coordinator, routers (N/A), end devices (N/A) */ sendACK(macHeader: MACHeader, nwkHeader: ZigbeeNWKHeader, apsHeader: ZigbeeAPSHeader): Promise<void>; /** * 05-3474-23 #4.4 (APS layer processing) * * SPEC COMPLIANCE NOTES: * - ✅ Handles DATA, ACK, INTERPAN frame types per spec definitions * - ✅ Performs duplicate rejection using APS counter + source addressing * - ✅ Performs fragmentation reassembly and forwards completed payloads upward * - ⚠️ INTERPAN frames not supported (throws) - spec optional for coordinators * - ⚠️ Fragment reassembly lacks payload size guard (tracked via CONFIG_APS_FRAGMENT_REASSEMBLY_TIMEOUT_MS) * DEVICE SCOPE: Coordinator, routers (N/A), end devices (N/A) */ processFrame(data: Buffer, macHeader: MACHeader, nwkHeader: ZigbeeNWKHeader, apsHeader: ZigbeeAPSHeader, lqa: number): Promise<void>; /** * 05-3474-23 #4.4.11 (APS command frames) * * SPEC COMPLIANCE NOTES: * - ✅ Encodes APS command header with appropriate delivery mode and security bit per parameters * - ✅ Integrates with NWK/ MAC handlers for routing + source routing * - ✅ Supports APS security header injection (LOAD/TRANSPORT keys) as required by TC flows * - ⚠️ disableACKRequest used for certain commands (e.g., TRANSPORT_KEY) despite spec recommending ACKs * - ⚠️ TLV extensions not yet supported (R23 features) * DEVICE SCOPE: Coordinator, routers (N/A), end devices (N/A) * * @param cmdId APS command identifier * @param finalPayload Fully encoded APS command payload (including cmdId) * @param nwkDiscoverRoute NWK discovery mode * @param nwkSecurity Whether to apply NWK security * @param nwkDest16 Destination network address * @param nwkDest64 Destination IEEE address (optional) * @param apsDeliveryMode Delivery mode (unicast/broadcast) * @param apsSecurityHeader Optional APS security header definition * @param disableACKRequest Whether to suppress APS ACK request * @returns True if success sending (or indirect transmission) */ sendCommand(cmdId: ZigbeeAPSCommandId, finalPayload: Buffer, nwkDiscoverRoute: ZigbeeNWKRouteDiscovery, nwkSecurity: boolean, nwkDest16: number | undefined, nwkDest64: bigint | undefined, apsDeliveryMode: ZigbeeAPSDeliveryMode.UNICAST | ZigbeeAPSDeliveryMode.BCAST, apsSecurityHeader: ZigbeeSecurityHeader | undefined, disableACKRequest?: boolean): Promise<boolean>; /** * 05-3474-23 #4.4.11 (APS command processing) * * SPEC COMPLIANCE NOTES: * - ✅ Dispatches APS command IDs to the appropriate handler per Table 4-28 * - ✅ Logs unsupported commands for diagnostics without crashing the stack * - ✅ Passes MAC/NWK headers to downstream handlers for security context decisions * - ⚠️ TLV parsing for extended commands still TODO (handlers emit TODO markers) * DEVICE SCOPE: Coordinator, routers (N/A), end devices (N/A) */ processCommand(data: Buffer, macHeader: MACHeader, nwkHeader: ZigbeeNWKHeader, apsHeader: ZigbeeAPSHeader): Promise<void>; /** * 05-3474-23 #4.4.11.1 * * SPEC COMPLIANCE NOTES: * - ✅ Handles all mandated key types (NWK, Trust Center, Application) and logs metadata * - ✅ Stages pending network key when addressed to coordinator or wildcard destination * - ✅ Preserves raw key material for subsequent SWITCH_KEY activation * - ⚠️ TLV extensions for enhanced security fields remain unparsed (TODO markers) * - ⚠️ Application key handling currently limited to storage; partner attribute updates pending * DEVICE SCOPE: Coordinator, routers (N/A), end devices (N/A) */ processTransportKey(data: Buffer, offset: number, macHeader: MACHeader, nwkHeader: ZigbeeNWKHeader, _apsHeader: ZigbeeAPSHeader): number; /** * 05-3474-23 #4.4.11.1 * * SPEC COMPLIANCE NOTES: * - ✅ Correctly uses CMD_KEY_TC_LINK type (0x01) per spec Table 4-17 * - ✅ Uses UNICAST delivery mode as required by spec * - ✅ Applies both NWK security (true) and APS security (LOAD key) per spec #4.4.1.5 * - ✅ Includes destination64 and source64 (TC eui64) as mandated * - ⚠️ TODO: TLVs not implemented (optional but recommended for R23+ features) * - ⚠️ TODO: Tunneling support not implemented (optional per spec #4.6.3.7) * - ❓ UNCERTAIN: Using LOAD keyId for APS encryption - spec says "link key" but LOAD is typically used for TC link key transport * - ✅ Frame counter uses TC key counter (nextTCKeyFrameCounter) which is correct * - ✅ MIC length 4 bytes as per security spec requirements * DEVICE SCOPE: Trust Center * * @param nwkDest16 * @param key SHALL contain the link key that SHOULD be used for APS encryption * @param destination64 SHALL contain the address of the device which SHOULD use this link key * @returns */ sendTransportKeyTC(nwkDest16: number, key: Buffer, destination64: bigint): Promise<boolean>; /** * 05-3474-23 #4.4.11.1 #4.4.11.1.3.2 * * SPEC COMPLIANCE NOTES: * - ✅ Correctly uses CMD_KEY_STANDARD_NWK type (0x00) per spec Table 4-17 * - ✅ Includes seqNum, destination64, and source64 as required by spec * - ✅ Uses UNICAST delivery mode as appropriate for joining device * - ⚠️ DESIGN CHOICE: Uses NWK security=false, APS security=true with TRANSPORT keyId * - Spec #4.4.1.5 states "a device receiving an APS transport key command MAY choose whether or not APS encryption is required" * - Implementation chooses APS encryption for initial join security * - Alternative (commented out) uses NWK=true, APS=false which is also valid per spec * - ⚠️ SPEC COMPLIANCE: disableACKRequest=true follows observed behavior in sniffs but spec #4.4.11 says: * "All commands except TUNNEL SHALL request acknowledgement" - this appears to violate spec * However, TRANSPORT_KEY during initial join may not receive ACK due to lack of NWK key * - ✅ Frame counter uses TC key counter which is correct for TRANSPORT keyId * - ✅ For distributed networks (no TC), source64 should be 0xFFFFFFFFFFFFFFFF per spec - code correctly uses eui64 (centralized TC) * - ✅ Broadcast destination64 handling sets all-zero string when using NWK broadcast per spec * DEVICE SCOPE: Trust Center * * @param nwkDest16 * @param key SHALL contain a network key * @param seqNum SHALL contain the sequence number associated with this network key * @param destination64 SHALL contain the address of the device which SHOULD use this network key * If the network key is sent to a broadcast address, the destination address subfield SHALL be set to the all-zero string and SHALL be ignored upon reception. * @returns */ sendTransportKeyNWK(nwkDest16: number, key: Buffer, seqNum: number, destination64: bigint): Promise<boolean>; /** * 05-3474-23 #4.4.11.1 #4.4.11.1.3.3 * * SPEC COMPLIANCE NOTES: * - ✅ Sets CMD_KEY_APP_LINK (0x03) and includes partner64 + initiator flag per Table 4-17 * - ✅ Applies APS security with TRANSPORT keyId (shared TC link key) while suppressing NWK security (permitted) * - ✅ Supports mirrored delivery (initiator + partner) when invoked twice in Request Key flow * - ⚠️ TODO: Add TLV support for enhanced security context (R23) * - ⚠️ TODO: Consider tunneling for indirect partners per spec #4.6.3.7 * DEVICE SCOPE: Trust Center */ sendTransportKeyAPP(nwkDest16: number, key: Buffer, partner: bigint, initiatorFlag: boolean): Promise<boolean>; /** * 05-3474-23 #4.4.11.2 * * SPEC COMPLIANCE NOTES: * - ✅ Correctly decodes all mandatory fields: device64, device16, status * - ⚠️ TODO: TLVs not decoded (optional but recommended for R23+ features) * - ✅ Handles 4 status codes as per spec: * 0x00 = Standard Device Secured Rejoin (updates device state via associate) * 0x01 = Standard Device Unsecured Join * 0x02 = Device Left * 0x03 = Standard Device Trust Center Rejoin * - ⚠️ IMPLEMENTATION: Status 0x01 (Unsecured Join) handling: * - Calls context associate with initial join=true ✅ * - Sets neighbor=false ✅ (device joined through router) * - allowOverride=true ✅ (was allowed by parent) * - Creates source route through parent ✅ * - Sends TUNNEL(TRANSPORT_KEY) to parent for relay ✅ * - ⚠️ SPEC CONCERN: Tunneling TRANSPORT_KEY for nested joins: * - Uses TUNNEL command per spec #4.6.3.7 ✅ * - Encrypts tunneled APS frame with TRANSPORT keyId ✅ * - However, should verify parent can relay before trusting join * - ✅ Status 0x03 (TC Rejoin) re-distributes NWK key when device lacks latest sequence * - ⚠️ Status 0x02 (Device Left) handling uses onDisassociate - spec says "informative only, should not take action" * This may be non-compliant as it actively removes the device * * SECURITY CONCERN: * - Unsecured joins through routers rely heavily on parent router trust * - No verification of parent's claim about device capabilities * - Source route created immediately may be premature if join fails * DEVICE SCOPE: Trust Center */ processUpdateDevice(data: Buffer, offset: number, macHeader: MACHeader, nwkHeader: ZigbeeNWKHeader, _apsHeader: ZigbeeAPSHeader): Promise<number>; /** * 05-3474-23 #4.4.11.2 * * @param nwkDest16 device that SHALL be sent the update information * @param device64 device whose status is being updated * @param device16 device whose status is being updated * @param status Indicates the updated status of the device given by the device64 parameter: * - 0x00 = Standard Device Secured Rejoin * - 0x01 = Standard Device Unsecured Join * - 0x02 = Device Left * - 0x03 = Standard Device Trust Center Rejoin * - 0x04 – 0x07 = Reserved * @param tlvs as relayed during Network Commissioning * @returns * DEVICE SCOPE: Coordinator, Routers (N/A) */ sendUpdateDevice(nwkDest16: number, device64: bigint, device16: number, status: number): Promise<boolean>; /** * 05-3474-23 #4.4.11.3 * * SPEC COMPLIANCE: * - ✅ Correctly decodes target IEEE address (childInfo) * - ✅ Issues NWK leave to child and removes from device tables * - ⚠️ Does not notify parent router beyond leave (spec expects UPDATE_DEVICE relays) * - ⚠️ Parent role handling limited to direct coordinator actions * DEVICE SCOPE: Coordinator, Routers (N/A) */ processRemoveDevice(data: Buffer, offset: number, macHeader: MACHeader, nwkHeader: ZigbeeNWKHeader, _apsHeader: ZigbeeAPSHeader): Promise<number>; /** * 05-3474-23 #4.4.11.3 * * SPEC COMPLIANCE: * - ✅ Includes target IEEE address * - ✅ Applies NWK + APS LOAD encryption * - ✅ Unicast to parent router * DEVICE SCOPE: Trust Center * * NOTE: Trust Center sends this to parent router, which should then remove child * * @param nwkDest16 parent * @param target64 * @returns */ sendRemoveDevice(nwkDest16: number, target64: bigint): Promise<boolean>; /** * 05-3474-23 #4.4.11.4 #4.4.5.2.3 * * SPEC COMPLIANCE NOTES: * - ✅ Rejects unencrypted APS frames as mandated (request MUST be APS secured) * - ✅ Honors Trust Center policies: allowTCKeyRequest / allowAppKeyRequest gates * - ✅ Returns NWK, TC, or APP link keys through appropriate TRANSPORT_KEY helpers * - ✅ Derives/stores application link keys via StackContext for partner distribution * - ⚠️ TODO: Implement ApplicationKeyRequestPolicy.ONLY_APPROVED enforcement * - ⚠️ TODO: Implement TrustCenterKeyRequestPolicy.ONLY_PROVISIONAL enforcement * - ⚠️ TODO: Track apsDeviceKeyPairSet per spec Annex B for negotiated keys * DEVICE SCOPE: Trust Center */ processRequestKey(data: Buffer, offset: number, macHeader: MACHeader, nwkHeader: ZigbeeNWKHeader, apsHeader: ZigbeeAPSHeader): Promise<number>; /** * 05-3474-23 #4.4.11.4 (APS Request Key) * * SPEC COMPLIANCE NOTES: * - ✅ Encodes keyType and optional partner64 fields per Table 4-18 * - ✅ Uses UNICAST delivery with NWK security as mandated * - ⚠️ Application key partner validation limited to lookup in device table * DEVICE SCOPE: Coordinator, routers (N/A), end devices (N/A) * * @param nwkDest16 * @param keyType SHALL be set to the key being requested * - 0x02: App link key * - 0x04: TC link key * @param partner64 When the RequestKeyType field is 2 (that is, an application key), * the partner address field SHALL contain the extended 64-bit address of the partner device that SHALL be sent the key. * Both the partner device and the device originating the request-key command will be sent the key. * @returns */ sendRequestKey(nwkDest16: number, keyType: 0x02, partner64: bigint): Promise<boolean>; sendRequestKey(nwkDest16: number, keyType: 0x04): Promise<boolean>; /** * 05-3474-23 #4.4.11.3 * * SPEC COMPLIANCE: * - ✅ Decodes sequence number identifying the pending network key * - ✅ Activates staged key via StackContext.activatePendingNetworkKey * - ✅ Resets NWK frame counter following activation * - ⚠️ Pending key staging remains prerequisite (TRANSPORT_KEY) * DEVICE SCOPE: Coordinator, routers (N/A), end devices (N/A) */ processSwitchKey(data: Buffer, offset: number, macHeader: MACHeader, nwkHeader: ZigbeeNWKHeader, _apsHeader: ZigbeeAPSHeader): number; /** * 05-3474-23 #4.4.11.5 * * SPEC COMPLIANCE: * - ✅ Includes sequence number associated with staged network key * - ✅ Broadcast or unicast delivery * - ✅ Applies NWK security only (per spec expectation) * - ⚠️ Relies on caller to stage key via TRANSPORT_KEY before invocation * DEVICE SCOPE: Trust Center * * @param nwkDest16 * @param seqNum SHALL contain the sequence number identifying the network key to be made active. * @returns */ sendSwitchKey(nwkDest16: number, seqNum: number): Promise<boolean>; /** * 05-3474-23 #4.4.11.6 * * SPEC COMPLIANCE: * - ✅ Correctly decodes destination address * - ✅ Extracts tunneled APS command frame * - ✅ Validates structure * - ❌ NOT IMPLEMENTED: Tunnel forwarding (only logs) * - ❌ MISSING: Should extract and forward tunneled command to destination * - ❌ MISSING: Security context validation * * IMPACT: Not applicable for Coordinator/Trust Center * DEVICE SCOPE: Coordinator, routers (N/A), end devices (N/A) */ processTunnel(data: Buffer, offset: number, macHeader: MACHeader, nwkHeader: ZigbeeNWKHeader, _apsHeader: ZigbeeAPSHeader): number; /** * 05-3474-23 #4.4.11.6 * * SPEC COMPLIANCE: * - ✅ Includes destination64 * - ✅ Encapsulates APS command frame * - ✅ Applies APS TRANSPORT encryption * - ✅ NO ACK request (per spec exception - TUNNEL is the only APS command without ACK) * - ✅ Used correctly for nested device joins (TRANSPORT_KEY delivery through routers) * DEVICE SCOPE: Trust Center * * @param nwkDest16 * @param destination64 SHALL be the 64-bit extended address of the device that is to receive the tunneled command * @param tApsCmdFrame SHALL be the APS command payload to be sent to the destination * @returns */ sendTunnel(nwkDest16: number, destination64: bigint, tApsCmdFrame: Buffer): Promise<boolean>; /** * 05-3474-23 #4.4.11.7 * * SPEC COMPLIANCE NOTES: * - ✅ Decodes keyType, source64, and keyHash correctly * - ✅ Filters out broadcast frames (macHeader.source16 !== BCAST_ADDR) as required * - ✅ Verifies TC link key hash for keyType=CMD_KEY_TC_LINK (0x01) * - ✅ Returns appropriate status codes: * - 0x00 (SUCCESS) when hash matches * - 0xad (SECURITY_FAILURE) when hash doesn't match * - 0xa3 (ILLEGAL_REQUEST) for APP_MASTER in TC * - 0xaa (NOT_SUPPORTED) for unknown key types * - ⚠️ SPEC COMPLIANCE: Hash verification uses pre-computed tcVerifyKeyHash from context * - Spec B.1.4: hash should be keyed hash function with input string '0x03' * - Implementation appears correct (context.tcVerifyKeyHash is computed correctly) * - ⚠️ Not valid for distributed mode but implementation is never distributed mode * - ✅ Sends CONFIRM_KEY in response with appropriate status * - ❓ UNCERTAIN: keyType=CMD_KEY_APP_MASTER (0x02) returns ILLEGAL_REQUEST for TC * - Spec is unclear if TC should reject this or if it's valid in some scenarios * - ✅ Uses source64 parameter correctly in CONFIRM_KEY response * * NOTE: This command is critical for security - device proves it has the correct key * DEVICE SCOPE: Trust Center */ processVerifyKey(data: Buffer, offset: number, macHeader: MACHeader, nwkHeader: ZigbeeNWKHeader, _apsHeader: ZigbeeAPSHeader): Promise<number>; /** * 05-3474-23 #4.4.11.7 (APS Verify Key) * * SPEC COMPLIANCE NOTES: * - ✅ Sends verification hash payload (16 bytes) together with keyType and source64 * - ✅ Unicast delivery with NWK security as required by Trust Center procedures * - ⚠️ Caller responsible for providing correct hash derived per Annex B * DEVICE SCOPE: Routers (N/A), end devices (N/A) * * @param nwkDest16 * @param keyType type of key being verified * @param source64 SHALL be the 64-bit extended address of the partner device that the destination shares the link key with * @param hash outcome of executing the specialized keyed hash function specified in section B.1.4 using a key with the 1-octet string ‘0x03’ as the input string * The resulting value SHALL NOT be used as a key for encryption or decryption * @returns */ sendVerifyKey(nwkDest16: number, keyType: number, source64: bigint, hash: Buffer): Promise<boolean>; /** * 05-3474-23 #4.4.11.8 (APS Confirm Key) * * SPEC COMPLIANCE NOTES: * - ✅ Parses status, keyType, destination64 per Table 4-19 * - ✅ Used primarily for logging; state updates happen in sendConfirmKey * - ⚠️ No validation of status/keyType beyond logging (TC expects follow-up handling elsewhere) * DEVICE SCOPE: Routers (N/A), end devices (N/A) */ processConfirmKey(data: Buffer, offset: number, macHeader: MACHeader, nwkHeader: ZigbeeNWKHeader, _apsHeader: ZigbeeAPSHeader): number; /** * 05-3474-23 #4.4.11.8 * * SPEC COMPLIANCE NOTES: * - ✅ Sends CONFIRM_KEY with all required fields: status, keyType, destination64 * - ✅ Uses UNICAST delivery mode as required * - ✅ Applies NWK security (true) as expected for TC communications * - ⚠️ CRITICAL SPEC QUESTION: Uses LINK keyId for APS security * - Comment says "XXX: TRANSPORT?" indicating uncertainty * - Spec #4.4.11.8 doesn't explicitly state which keyId to use * - LINK (0x03) suggests using the link key being confirmed * - TRANSPORT (0x05) would use TC link key as transport * - THIS NEEDS VERIFICATION AGAINST SPEC AND PACKET CAPTURES * - ✅ Uses nextTCKeyFrameCounter() which is correct for TC->device communications * - ✅ Sets device.authorized = true after successful CONFIRM_KEY send * - ✅ Triggers onDeviceAuthorized callback via setImmediate (non-blocking) * - ⚠️ TIMING CONCERN: Sets authorized=true immediately after send, not after ACK * - May cause race condition if CONFIRM_KEY fails to deliver * - Should possibly wait for ACK or rely on retry mechanism * - ✅ Only sets authorized for devices in deviceTable * * CRITICAL: This is the final step in device authorization - must be correct! * DEVICE SCOPE: Trust Center * * @param nwkDest16 * @param status 1-byte status code indicating the result of the operation. See Table 2.27 * @param keyType the type of key being verified * @param destination64 SHALL be the 64-bit extended address of the source device of the Verify-Key message * @returns */ sendConfirmKey(nwkDest16: number, status: number, keyType: number, destination64: bigint): Promise<boolean>; /** * R23 FEATURE - 05-3474-23 #4.4.11.9 * * SPEC COMPLIANCE: * - ⚠️ R23 feature with minimal implementation * - ✅ Structure parsing exists (destination64) * - ❌ NOT IMPLEMENTED: Message relaying functionality * - ❌ NOT IMPLEMENTED: TLV processing * - ❌ NOT IMPLEMENTED: Fragment handling * * USE CASES: ZVD (Zigbee Virtual Devices), Zigbee Direct - NOT SUPPORTED * * NOTE: Non-critical for Zigbee 3.0 PRO networks * DEVICE SCOPE: Trust Center */ processRelayMessageDownstream(data: Buffer, offset: number, macHeader: MACHeader, nwkHeader: ZigbeeNWKHeader, _apsHeader: ZigbeeAPSHeader): number; /** * R23 FEATURE - 05-3474-23 #4.4.11.10 * * SPEC COMPLIANCE: * - ⚠️ R23 feature with minimal implementation * - ✅ Structure parsing exists (source64) * - ❌ NOT IMPLEMENTED: Message relaying functionality * - ❌ NOT IMPLEMENTED: TLV processing * - ❌ NOT IMPLEMENTED: Fragment handling * * USE CASES: ZVD (Zigbee Virtual Devices), Zigbee Direct - NOT SUPPORTED * * NOTE: Non-critical for Zigbee 3.0 PRO networks * DEVICE SCOPE: Routers (N/A), end devices (N/A) */ processRelayMessageUpstream(data: Buffer, offset: number, macHeader: MACHeader, nwkHeader: ZigbeeNWKHeader, _apsHeader: ZigbeeAPSHeader): number; /** * 05-3474-23 #2.4.4.2.3 * * Generate LQI (Link Quality Indicator) table response for coordinator. * ZDO response to LQI_TABLE_REQUEST. * * SPEC COMPLIANCE NOTES: * - ✅ Produces response header fields (status, totalEntries, startIndex, entryCount) * - ✅ Encodes per-neighbor records with device type, permit-join, depth, and LQI * - ⚠️ Relationship/permit-join/depth fields currently stubbed with TODO markers * - ⚠️ Table truncated to 255 entries without pagination continuation handling * DEVICE SCOPE: Coordinator * * @param startIndex The index to start the table entries from * @returns Buffer containing the LQI table response */ getLQITableResponse(startIndex: number): Buffer; /** * 05-3474-23 #2.4.4.3.3 * * Generate routing table response for coordinator. * ZDO response to ROUTING_TABLE_REQUEST. * NOTE: Only outputs the best source route for each entry in the table (clipped to max 255 entries). * * SPEC COMPLIANCE NOTES: * - ✅ Populates routing table response header and entry layout per Table 2-80 * - ✅ Derives next hop from best known source route for each destination * - ⚠️ Status flags (memoryConstrained, manyToOne, routeRecordRequired) currently fixed to 0/TODO * - ⚠️ Response clipped to 255 entries without continuation index support * DEVICE SCOPE: Coordinator * * @param startIndex The index to start the table entries from * @returns Buffer containing the routing table response */ getRoutingTableResponse(startIndex: number): Buffer; /** * Generate ZDO response payload for coordinator based on cluster ID. * @param clusterId The ZDO cluster ID * @param requestData The request payload buffer * @returns Response buffer or undefined if cluster not supported */ getCoordinatorZDOResponse(clusterId: number, requestData: Buffer): Buffer | undefined; /** * Check if ZDO request is intended for coordinator. * @param clusterId The ZDO cluster ID * @param nwkDst16 Network destination address (16-bit) * @param nwkDst64 Network destination address (64-bit) * @param data The ZDO request payload * @returns true if request targets coordinator */ isZDORequestForCoordinator(clusterId: number, nwkDst16: number | undefined, nwkDst64: bigint | undefined, data: Buffer): boolean; /** * Respond to ZDO requests aimed at coordinator if needed. * @param data ZDO request payload * @param clusterId ZDO cluster ID * @param nwkDest16 Network destination address (16-bit) * @param nwkDest64 Network destination address (64-bit) */ respondToCoordinatorZDORequest(data: Buffer, clusterId: number, nwkDest16: number | undefined, nwkDest64: bigint | undefined): Promise<void>; }