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:
tbrennan3
2011-09-30 20:00:48 +00:00
parent a25a7a238d
commit 7eb2109dc4
4 changed files with 62 additions and 24 deletions
+9 -3
View File
@@ -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 ) {
+8 -2
View File
@@ -96,16 +96,22 @@ 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
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
+15 -10
View File
@@ -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,13 +368,6 @@ 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
View File
@@ -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>