diff --git a/bacnet-stack/demo/handler/h_routed_npdu.c b/bacnet-stack/demo/handler/h_routed_npdu.c index 3f321ce7..a805764c 100644 --- a/bacnet-stack/demo/handler/h_routed_npdu.c +++ b/bacnet-stack/demo/handler/h_routed_npdu.c @@ -203,9 +203,15 @@ static void routed_apdu_handler( * 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. - * Upper level handlers knew that this was sent as a bcast, - * but our only way to guess at that here is if the dest->adr + * 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 ) { diff --git a/bacnet-stack/include/bvlc.h b/bacnet-stack/include/bvlc.h index e06c198d..e1ee1eea 100644 --- a/bacnet-stack/include/bvlc.h +++ b/bacnet-stack/include/bvlc.h @@ -96,15 +96,21 @@ extern "C" { struct sockaddr_in; /* Defined elsewhere, needed here. */ /* 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, uint8_t * npdu, 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 * as a foreign device. */ 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 } diff --git a/bacnet-stack/src/bip.c b/bacnet-stack/src/bip.c index d4cb52d7..ef8821ef 100644 --- a/bacnet-stack/src/bip.c +++ b/bacnet-stack/src/bip.c @@ -234,6 +234,7 @@ uint16_t bip_receive( struct sockaddr_in sin = { 0 }; socklen_t sin_len = sizeof(sin); uint16_t i = 0; + int function = 0; /* Make sure the socket is open */ if (BIP_Socket < 0) @@ -273,8 +274,19 @@ uint16_t bip_receive( /* the signature of a BACnet/IP packet */ if (pdu[0] != BVLL_TYPE_BACNET_IP) 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 */ if ((sin.sin_addr.s_addr == BIP_Address.s_addr) && (sin.sin_port == BIP_Port)) { @@ -327,7 +339,7 @@ uint16_t bip_receive( #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_port, &pdu[8], 2); if ((sin.sin_addr.s_addr == BIP_Address.s_addr) && @@ -356,14 +368,7 @@ uint16_t bip_receive( 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; } diff --git a/bacnet-stack/src/bvlc.c b/bacnet-stack/src/bvlc.c index fe324cc7..d2bad0be 100644 --- a/bacnet-stack/src/bvlc.c +++ b/bacnet-stack/src/bvlc.c @@ -51,13 +51,15 @@ * 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 */ 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; +/** 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 * BBMD needs to handle its services. @@ -823,7 +825,6 @@ uint16_t bvlc_receive( struct sockaddr_in original_sin = { 0 }; struct sockaddr_in dest = { 0 }; socklen_t sin_len = sizeof(sin); - int function_type = 0; int received_bytes = 0; uint16_t result_code = 0; uint16_t i = 0; @@ -869,12 +870,12 @@ uint16_t bvlc_receive( if (npdu[0] != BVLL_TYPE_BACNET_IP) { return 0; } - function_type = npdu[1]; + BVLC_Function_Code = npdu[1]; /* decode the length of the PDU - length is inclusive of BVLC */ (void) decode_unsigned16(&npdu[2], &npdu_len); /* subtract off the BVLC header */ npdu_len -= 4; - switch (function_type) { + switch (BVLC_Function_Code) { case BVLC_RESULT: /* Upon receipt of a BVLC-Result message containing a result code 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. * 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 npdu [in] The received buffer. * @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, uint8_t * npdu, uint16_t received_bytes) { uint16_t result_code = 0; /* aka, BVLC_RESULT_SUCCESSFUL_COMPLETION */ - uint8_t function_type = npdu[1]; /* The BVLC function */ - switch (function_type) { + BVLC_Function_Code = npdu[1]; /* The BVLC function */ + switch (BVLC_Function_Code) { case BVLC_RESULT: if ( received_bytes >= 6) { /* This is the result of our foreign device registration */ @@ -1276,6 +1281,7 @@ void bvlc_for_non_bbmd( case BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK: result_code = BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK; break; + /* case BVLC_FORWARDED_NPDU: */ /* case BVLC_ORIGINAL_UNICAST_NPDU: */ /* case BVLC_ORIGINAL_BROADCAST_NPDU: */ default: @@ -1300,6 +1306,21 @@ BACNET_BVLC_RESULT bvlc_get_last_result() 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 #include #include