Added the ability to ask for the BVLC Function Code in the lower layers; particular need was to recognize bcasts and not respond with Reject-Message-to-Network.
This commit is contained in:
@@ -203,9 +203,15 @@ static void routed_apdu_handler(
|
|||||||
* was broadcast to us, we should assume "someone else" is handling
|
* was broadcast to us, we should assume "someone else" is handling
|
||||||
* it and not get involved (ie, send a Reject-Message).
|
* it and not get involved (ie, send a Reject-Message).
|
||||||
* Since we can't reach other routers that src couldn't already reach,
|
* 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.
|
* we don't try the standard path of asking Who-Is-Router-to-Network. */
|
||||||
* Upper level handlers knew that this was sent as a bcast,
|
#if defined(BACDL_BIP)
|
||||||
* but our only way to guess at that here is if the dest->adr
|
/* 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.
|
* is absent, then we know this is some sort of bcast.
|
||||||
*/
|
*/
|
||||||
if ( dest->len > 0 ) {
|
if ( dest->len > 0 ) {
|
||||||
|
|||||||
@@ -96,15 +96,21 @@ extern "C" {
|
|||||||
struct sockaddr_in; /* Defined elsewhere, needed here. */
|
struct sockaddr_in; /* Defined elsewhere, needed here. */
|
||||||
|
|
||||||
/* Note any BVLC_RESULT code, or NAK the BVLL message in the unsupported cases. */
|
/* Note any BVLC_RESULT code, or NAK the BVLL message in the unsupported cases. */
|
||||||
void bvlc_for_non_bbmd(
|
int bvlc_for_non_bbmd(
|
||||||
struct sockaddr_in * sout,
|
struct sockaddr_in * sout,
|
||||||
uint8_t * npdu,
|
uint8_t * npdu,
|
||||||
uint16_t received_bytes);
|
uint16_t received_bytes);
|
||||||
|
|
||||||
/** Returns the last BVLL Result we received, either as the result of a BBMD
|
/* Returns the last BVLL Result we received, either as the result of a BBMD
|
||||||
* request we sent, or (if not a BBMD or Client), from trying to register
|
* request we sent, or (if not a BBMD or Client), from trying to register
|
||||||
* as a foreign device. */
|
* as a foreign device. */
|
||||||
BACNET_BVLC_RESULT bvlc_get_last_result();
|
BACNET_BVLC_RESULT bvlc_get_last_result();
|
||||||
|
|
||||||
|
/* Returns the current BVLL Function Code we are processing.
|
||||||
|
* We have to store this higher layer code for when the lower layers
|
||||||
|
* need to know what it is, especially to differentiate between
|
||||||
|
* BVLC_ORIGINAL_UNICAST_NPDU and BVLC_ORIGINAL_BROADCAST_NPDU. */
|
||||||
|
BACNET_BVLC_FUNCTION bvlc_get_function_code();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-11
@@ -234,6 +234,7 @@ uint16_t bip_receive(
|
|||||||
struct sockaddr_in sin = { 0 };
|
struct sockaddr_in sin = { 0 };
|
||||||
socklen_t sin_len = sizeof(sin);
|
socklen_t sin_len = sizeof(sin);
|
||||||
uint16_t i = 0;
|
uint16_t i = 0;
|
||||||
|
int function = 0;
|
||||||
|
|
||||||
/* Make sure the socket is open */
|
/* Make sure the socket is open */
|
||||||
if (BIP_Socket < 0)
|
if (BIP_Socket < 0)
|
||||||
@@ -273,8 +274,19 @@ uint16_t bip_receive(
|
|||||||
/* the signature of a BACnet/IP packet */
|
/* the signature of a BACnet/IP packet */
|
||||||
if (pdu[0] != BVLL_TYPE_BACNET_IP)
|
if (pdu[0] != BVLL_TYPE_BACNET_IP)
|
||||||
return 0;
|
return 0;
|
||||||
if ((pdu[1] == BVLC_ORIGINAL_UNICAST_NPDU) ||
|
|
||||||
(pdu[1] == BVLC_ORIGINAL_BROADCAST_NPDU)) {
|
if ( bvlc_for_non_bbmd(&sin, pdu, received_bytes) > 0 )
|
||||||
|
{
|
||||||
|
/* Handled, usually with a NACK. */
|
||||||
|
#if PRINT_ENABLED
|
||||||
|
fprintf(stderr, "BIP: BVLC discarded!\n");
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function = bvlc_get_function_code(); /* aka, pdu[1] */
|
||||||
|
if ((function == BVLC_ORIGINAL_UNICAST_NPDU) ||
|
||||||
|
(function == BVLC_ORIGINAL_BROADCAST_NPDU)) {
|
||||||
/* ignore messages from me */
|
/* ignore messages from me */
|
||||||
if ((sin.sin_addr.s_addr == BIP_Address.s_addr) &&
|
if ((sin.sin_addr.s_addr == BIP_Address.s_addr) &&
|
||||||
(sin.sin_port == BIP_Port)) {
|
(sin.sin_port == BIP_Port)) {
|
||||||
@@ -327,7 +339,7 @@ uint16_t bip_receive(
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (pdu[1] == BVLC_FORWARDED_NPDU) {
|
} else if (function == BVLC_FORWARDED_NPDU) {
|
||||||
memcpy(&sin.sin_addr.s_addr, &pdu[4], 4);
|
memcpy(&sin.sin_addr.s_addr, &pdu[4], 4);
|
||||||
memcpy(&sin.sin_port, &pdu[8], 2);
|
memcpy(&sin.sin_port, &pdu[8], 2);
|
||||||
if ((sin.sin_addr.s_addr == BIP_Address.s_addr) &&
|
if ((sin.sin_addr.s_addr == BIP_Address.s_addr) &&
|
||||||
@@ -356,14 +368,7 @@ uint16_t bip_receive(
|
|||||||
pdu_len = 0;
|
pdu_len = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
/* Handle, usually with a NACK. */
|
|
||||||
bvlc_for_non_bbmd(&sin, pdu, received_bytes);
|
|
||||||
#if PRINT_ENABLED
|
|
||||||
fprintf(stderr, "BIP: BVLC discarded!\n");
|
|
||||||
#endif
|
|
||||||
pdu_len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pdu_len;
|
return pdu_len;
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-8
@@ -51,13 +51,15 @@
|
|||||||
* Foreign Device Registration.
|
* Foreign Device Registration.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* if we are a foreign device, store the
|
/** if we are a foreign device, store the
|
||||||
remote BBMD address/port here in network byte order */
|
remote BBMD address/port here in network byte order */
|
||||||
static struct sockaddr_in Remote_BBMD;
|
static struct sockaddr_in Remote_BBMD;
|
||||||
|
|
||||||
/* result from a client request */
|
/** result from a client request */
|
||||||
BACNET_BVLC_RESULT BVLC_Result_Code = BVLC_RESULT_SUCCESSFUL_COMPLETION;
|
BACNET_BVLC_RESULT BVLC_Result_Code = BVLC_RESULT_SUCCESSFUL_COMPLETION;
|
||||||
|
|
||||||
|
/** The current BVLC Function Code being handled. */
|
||||||
|
BACNET_BVLC_FUNCTION BVLC_Function_Code = BVLC_RESULT; /* A safe default */
|
||||||
|
|
||||||
/* Define BBMD_ENABLED to get the functions that a
|
/* Define BBMD_ENABLED to get the functions that a
|
||||||
* BBMD needs to handle its services.
|
* BBMD needs to handle its services.
|
||||||
@@ -823,7 +825,6 @@ uint16_t bvlc_receive(
|
|||||||
struct sockaddr_in original_sin = { 0 };
|
struct sockaddr_in original_sin = { 0 };
|
||||||
struct sockaddr_in dest = { 0 };
|
struct sockaddr_in dest = { 0 };
|
||||||
socklen_t sin_len = sizeof(sin);
|
socklen_t sin_len = sizeof(sin);
|
||||||
int function_type = 0;
|
|
||||||
int received_bytes = 0;
|
int received_bytes = 0;
|
||||||
uint16_t result_code = 0;
|
uint16_t result_code = 0;
|
||||||
uint16_t i = 0;
|
uint16_t i = 0;
|
||||||
@@ -869,12 +870,12 @@ uint16_t bvlc_receive(
|
|||||||
if (npdu[0] != BVLL_TYPE_BACNET_IP) {
|
if (npdu[0] != BVLL_TYPE_BACNET_IP) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
function_type = npdu[1];
|
BVLC_Function_Code = npdu[1];
|
||||||
/* decode the length of the PDU - length is inclusive of BVLC */
|
/* decode the length of the PDU - length is inclusive of BVLC */
|
||||||
(void) decode_unsigned16(&npdu[2], &npdu_len);
|
(void) decode_unsigned16(&npdu[2], &npdu_len);
|
||||||
/* subtract off the BVLC header */
|
/* subtract off the BVLC header */
|
||||||
npdu_len -= 4;
|
npdu_len -= 4;
|
||||||
switch (function_type) {
|
switch (BVLC_Function_Code) {
|
||||||
case BVLC_RESULT:
|
case BVLC_RESULT:
|
||||||
/* Upon receipt of a BVLC-Result message containing a result code
|
/* Upon receipt of a BVLC-Result message containing a result code
|
||||||
of X'0000' indicating the successful completion of the
|
of X'0000' indicating the successful completion of the
|
||||||
@@ -1234,18 +1235,22 @@ int bvlc_register_with_bbmd(
|
|||||||
|
|
||||||
/** Note any BVLC_RESULT code, or NAK the BVLL message in the unsupported cases.
|
/** Note any BVLC_RESULT code, or NAK the BVLL message in the unsupported cases.
|
||||||
* Use this handler when you are not a BBMD.
|
* Use this handler when you are not a BBMD.
|
||||||
|
* Sets the BVLC_Function_Code in case it is needed later.
|
||||||
|
*
|
||||||
* @param sout [in] Socket address to send any NAK back to.
|
* @param sout [in] Socket address to send any NAK back to.
|
||||||
* @param npdu [in] The received buffer.
|
* @param npdu [in] The received buffer.
|
||||||
* @param received_bytes [in] How many bytes in npdu[].
|
* @param received_bytes [in] How many bytes in npdu[].
|
||||||
|
* @return Non-zero BVLC_RESULT_ code if we sent a response (NAK) to this
|
||||||
|
* BVLC message. If zero, may need further processing.
|
||||||
*/
|
*/
|
||||||
void bvlc_for_non_bbmd(
|
int bvlc_for_non_bbmd(
|
||||||
struct sockaddr_in * sout,
|
struct sockaddr_in * sout,
|
||||||
uint8_t * npdu,
|
uint8_t * npdu,
|
||||||
uint16_t received_bytes)
|
uint16_t received_bytes)
|
||||||
{
|
{
|
||||||
uint16_t result_code = 0; /* aka, BVLC_RESULT_SUCCESSFUL_COMPLETION */
|
uint16_t result_code = 0; /* aka, BVLC_RESULT_SUCCESSFUL_COMPLETION */
|
||||||
uint8_t function_type = npdu[1]; /* The BVLC function */
|
BVLC_Function_Code = npdu[1]; /* The BVLC function */
|
||||||
switch (function_type) {
|
switch (BVLC_Function_Code) {
|
||||||
case BVLC_RESULT:
|
case BVLC_RESULT:
|
||||||
if ( received_bytes >= 6) {
|
if ( received_bytes >= 6) {
|
||||||
/* This is the result of our foreign device registration */
|
/* This is the result of our foreign device registration */
|
||||||
@@ -1276,6 +1281,7 @@ void bvlc_for_non_bbmd(
|
|||||||
case BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK:
|
case BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK:
|
||||||
result_code = BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK;
|
result_code = BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK;
|
||||||
break;
|
break;
|
||||||
|
/* case BVLC_FORWARDED_NPDU: */
|
||||||
/* case BVLC_ORIGINAL_UNICAST_NPDU: */
|
/* case BVLC_ORIGINAL_UNICAST_NPDU: */
|
||||||
/* case BVLC_ORIGINAL_BROADCAST_NPDU: */
|
/* case BVLC_ORIGINAL_BROADCAST_NPDU: */
|
||||||
default:
|
default:
|
||||||
@@ -1300,6 +1306,21 @@ BACNET_BVLC_RESULT bvlc_get_last_result()
|
|||||||
return BVLC_Result_Code;
|
return BVLC_Result_Code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the current BVLL Function Code we are processing.
|
||||||
|
* We have to store this higher layer code for when the lower layers
|
||||||
|
* need to know what it is, especially to differentiate between
|
||||||
|
* BVLC_ORIGINAL_UNICAST_NPDU and BVLC_ORIGINAL_BROADCAST_NPDU.
|
||||||
|
*
|
||||||
|
* @return A BVLC_ code, such as BVLC_ORIGINAL_UNICAST_NPDU.
|
||||||
|
*/
|
||||||
|
BACNET_BVLC_FUNCTION bvlc_get_function_code()
|
||||||
|
{
|
||||||
|
return BVLC_Function_Code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user