static void My_NPDU_Handler( BACNET_ADDRESS * src, /* source address */ uint8_t * pdu, /* PDU data */ uint16_t pdu_len) { /* length PDU */ int apdu_offset = 0; BACNET_ADDRESS dest = { 0 }; BACNET_NPDU_DATA npdu_data = { 0 }; apdu_offset = npdu_decode(&pdu[0], &dest, src, &npdu_data); if (npdu_data.network_layer_message) { if (apdu_offset <= pdu_len) { My_Router_Handler(src, &npdu_data, &pdu[apdu_offset], (uint16_t) (pdu_len - apdu_offset)); } } else if ((apdu_offset > 0) && (apdu_offset <= pdu_len)) { if ((npdu_data.protocol_version == BACNET_PROTOCOL_VERSION) && ((dest.net == 0) || (dest.net == BACNET_BROADCAST_NETWORK))) { /* only handle the version that we know how to handle */ /* and we are not a router, so ignore messages with routing information cause they are not for us */ apdu_handler(src, &pdu[apdu_offset], (uint16_t) (pdu_len - apdu_offset)); } else { if (dest.net) { debug_printf("NPDU: DNET=%d. Discarded!\n", dest.net); } else { debug_printf("NPDU: BACnet Protocol Version=%d. Discarded!\n", npdu_data.protocol_version); } } } return; }
/** Handler for the NPDU portion of a received packet. * Aside from error-checking, if the NPDU doesn't contain routing info, * this handler doesn't do much besides stepping over the NPDU header * and passing the remaining bytes to the apdu_handler. * @note The routing (except src) and NCPI information, including * npdu_data->data_expecting_reply, are discarded. * @see routing_npdu_handler * * @ingroup MISCHNDLR * * @param src [out] Returned with routing source information if the NPDU * has any and if this points to non-null storage for it. * If src->net and src->len are 0 on return, there is no * routing source information. * This src describes the original source of the message when * it had to be routed to reach this BACnet Device, and this * is passed down into the apdu_handler; however, I don't * think this project's code has any use for the src info * on return from this handler, since the response has * already been sent via the apdu_handler. * @param pdu [in] Buffer containing the NPDU and APDU of the received packet. * @param pdu_len [in] The size of the received message in the pdu[] buffer. */ void npdu_handler( PORT_SUPPORT *portParams, BACNET_ADDRESS * src, /* source address */ uint8_t * pdu, /* PDU data */ uint16_t pdu_len) { /* length PDU */ int apdu_offset = 0; BACNET_ADDRESS dest = { 0 }; BACNET_NPDU_DATA npdu_data = { 0 }; /* only handle the version that we know how to handle */ if (pdu[0] == BACNET_PROTOCOL_VERSION) { apdu_offset = npdu_decode(&pdu[0], &dest, src, &npdu_data); if (npdu_data.network_layer_message) { /*FIXME: network layer message received! Handle it! */ #if PRINT_ENABLED fprintf(stderr, "NPDU: Network Layer Message discarded!\n"); #endif } else if ((apdu_offset > 0) && (apdu_offset <= pdu_len)) { if ((dest.net == 0) || (dest.net == BACNET_BROADCAST_NETWORK)) { /* only handle the version that we know how to handle */ /* and we are not a router, so ignore messages with routing information cause they are not for us */ if ((dest.net == BACNET_BROADCAST_NETWORK) && ((pdu[apdu_offset] & 0xF0) == PDU_TYPE_CONFIRMED_SERVICE_REQUEST)) { /* hack for 5.4.5.1 - IDLE */ /* ConfirmedBroadcastReceived */ /* then enter IDLE - ignore the PDU */ } else { apdu_handler(portParams, src, &pdu[apdu_offset], (uint16_t) (pdu_len - apdu_offset)); } } else { #if PRINT_ENABLED printf("NPDU: DNET=%u. Discarded!\n", (unsigned) dest.net); #endif } } } else { #if PRINT_ENABLED printf("NPDU: BACnet Protocol Version=%u. Discarded!\n", (unsigned) pdu[0]); #endif } return; }
/** An APDU pre-handler that makes sure that the subsequent APDU handler call * operates on the right Device Object(s), as addressed by the destination * (routing) information. * * @note Even when the destination is "routed" to our virtual BACnet network, * the src information does not need to change to reflect that (as it normally * would for a routed message) because the reply will be sent from the level * of the gateway Device. * * @param src [in] The BACNET_ADDRESS of the message's source. * @param dest [in] The BACNET_ADDRESS of the message's destination. * @param DNET_list [in] List of our reachable downstream BACnet Network numbers. * Normally just one valid entry; terminated with a -1 value. * @param apdu [in] The apdu portion of the request, to be processed. * @param apdu_len [in] The total (remaining) length of the apdu. */ static void routed_apdu_handler( BACNET_ADDRESS * src, BACNET_ADDRESS * dest, int *DNET_list, uint8_t * apdu, uint16_t apdu_len) { int cursor = 0; /* Starting hint */ bool bGotOne = false; if (!Routed_Device_Is_Valid_Network(dest->net, DNET_list)) { /* We don't know how to reach this one. * The protocol doesn't specifically state this, but if this message * was broadcast to us, we should assume "someone else" is handling * it and not get involved (ie, send a Reject-Message). * Since we can't reach other routers that src couldn't already reach, * we don't try the standard path of asking Who-Is-Router-to-Network. */ #if defined(BACDL_BIP) /* If wasn't unicast to us, must have been one of the bcast types. * Drop it. */ if (bvlc_get_function_code() != BVLC_ORIGINAL_UNICAST_NPDU) return; #endif /* Upper level handlers knew that this was sent as a bcast, * but our only other way to guess at that here is if the dest->adr * is absent, then we know this is some sort of bcast. */ if (dest->len > 0) { Send_Reject_Message_To_Network(src, NETWORK_REJECT_NO_ROUTE, dest->net); } /* else, silently drop it */ return; } while (Routed_Device_GetNext(dest, DNET_list, &cursor)) { apdu_handler(src, apdu, apdu_len); bGotOne = true; if (cursor < 0) /* If no more matches, */ break; /* We don't need to keep looking */ } if (!bGotOne) { /* Just silently drop this packet. */ } }
/** Handler for the NPDU portion of a received packet. * Aside from error-checking, if the NPDU doesn't contain routing info, * this handler doesn't do much besides stepping over the NPDU header * and passing the remaining bytes to the apdu_handler. * @note The routing (except src) and NCPI information, including * npdu_data->data_expecting_reply, are discarded. * @see routing_npdu_handler * * @ingroup MISCHNDLR * * @param src [out] Returned with routing source information if the NPDU * has any and if this points to non-null storage for it. * If src->net and src->len are 0 on return, there is no * routing source information. * This src describes the original source of the message when * it had to be routed to reach this BACnet Device, and this * is passed down into the apdu_handler; however, I don't * think this project's code has any use for the src info * on return from this handler, since the response has * already been sent via the apdu_handler. * @param pdu [in] Buffer containing the NPDU and APDU of the received packet. * @param pdu_len [in] The size of the received message in the pdu[] buffer. */ void npdu_handler( BACNET_ADDRESS * src, /* source address */ uint8_t * pdu, /* PDU data */ uint16_t pdu_len) { /* length PDU */ int apdu_offset = 0; BACNET_ADDRESS dest = { 0 }; BACNET_NPDU_DATA npdu_data = { 0 }; /* only handle the version that we know how to handle */ if (pdu[0] == BACNET_PROTOCOL_VERSION) { apdu_offset = npdu_decode(&pdu[0], &dest, src, &npdu_data); if (npdu_data.network_layer_message) { /*FIXME: network layer message received! Handle it! */ #ifdef PRINT_ENABLE fprintf(stderr, "NPDU: Network Layer Message discarded!\n"); #endif } else if ((apdu_offset > 0) && (apdu_offset <= pdu_len)) { if ((dest.net == 0) || (dest.net == BACNET_BROADCAST_NETWORK)) { /* only handle the version that we know how to handle */ /* and we are not a router, so ignore messages with routing information cause they are not for us */ apdu_handler(src, &pdu[apdu_offset], (uint16_t) (pdu_len - apdu_offset)); } else { #ifdef PRINT_ENABLE fprintf(stderr, "NPDU: DNET=%u. Discarded!\n", (unsigned) dest.net); #endif } } } else { #ifdef PRINT_ENABLE fprintf(stderr, "NPDU: BACnet Protocol Version=%u. Discarded!\n", (unsigned) pdu[0]); #endif } return; }