Skip to content

Commit

Permalink
Issues/issue 811 mstpcap considers valid frames as invalid if used as…
Browse files Browse the repository at this point in the history
… a standalone tool (bacnet-stack#812)

* Fixed mstpcap utility by setting This-Station to the MS/TP promiscuous mode address 255.

* Fixed MS/TP receive filter for valid data frames which was missing.

* Fixed MS/TP zero-config duplicate node detection

* Reset silence during MS/TP capture after writing packet to prevent endless packets when stream is interrupted.
  • Loading branch information
skarg authored Oct 15, 2024
1 parent 2b58f5b commit ac7dee0
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 42 deletions.
7 changes: 5 additions & 2 deletions apps/mstpcap/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,8 @@ static void print_help(const char *filename)
filename);
}

/* initialize some of the variables in the MS/TP Receive structure */
/* initialize some of the variables in the MS/TP Receive structure
after each packet write */
static void mstp_structure_init(struct mstp_port_struct_t *mstp_port)
{
if (mstp_port) {
Expand All @@ -983,9 +984,11 @@ static void mstp_structure_init(struct mstp_port_struct_t *mstp_port)
mstp_port->HeaderCRCActual = 0;
mstp_port->Index = 0;
mstp_port->EventCount = 0;
mstp_port->DataRegister = 0xFF;
mstp_port->ReceivedInvalidFrame = false;
mstp_port->ReceivedValidFrame = false;
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
mstp_port->SilenceTimerReset(NULL);
}
}

Expand All @@ -1003,7 +1006,7 @@ int main(int argc, char *argv[])
MSTP_Port.InputBufferSize = sizeof(RxBuffer);
MSTP_Port.OutputBuffer = &TxBuffer[0];
MSTP_Port.OutputBufferSize = sizeof(TxBuffer);
MSTP_Port.This_Station = 127;
MSTP_Port.This_Station = MSTP_BROADCAST_ADDRESS;
MSTP_Port.Nmax_info_frames = 1;
MSTP_Port.Nmax_master = 127;
MSTP_Port.SilenceTimer = Timer_Silence;
Expand Down
81 changes: 41 additions & 40 deletions src/bacnet/datalink/mstp.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,17 @@ void MSTP_Create_And_Send_Frame(
/* FIXME: be sure to reset SilenceTimer() after each octet is sent! */
}

static bool MSTP_Frame_For_Us(struct mstp_port_struct_t *mstp_port)
{
if ((mstp_port->DestinationAddress == mstp_port->This_Station) ||
(mstp_port->DestinationAddress == MSTP_BROADCAST_ADDRESS) ||
(mstp_port->This_Station == MSTP_BROADCAST_ADDRESS)) {
return true;
}

return false;
}

/**
* @brief Finite State Machine for receiving an MSTP frame
* @param mstp_port MSTP port context data
Expand Down Expand Up @@ -429,30 +440,22 @@ void MSTP_Receive_Frame_FSM(struct mstp_port_struct_t *mstp_port)
} else {
if (mstp_port->DataLength == 0) {
/* NoData */
if ((mstp_port->DestinationAddress ==
mstp_port->This_Station) ||
(mstp_port->DestinationAddress ==
MSTP_BROADCAST_ADDRESS) ||
(mstp_port->This_Station ==
MSTP_BROADCAST_ADDRESS)) {
if (MSTP_Frame_For_Us(mstp_port)) {
printf_receive_data(
"%s",
mstptext_frame_type(
(unsigned)mstp_port->FrameType));
/* indicate that a frame with no data has been
* received */
mstp_port->ReceivedValidFrame = true;
} else {
/* NotForUs */
mstp_port->ReceivedInvalidFrame = true;
}
/* wait for the start of the next frame. */
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
} else {
/* receive the data portion of the frame. */
if ((mstp_port->DestinationAddress ==
mstp_port->This_Station) ||
(mstp_port->DestinationAddress ==
MSTP_BROADCAST_ADDRESS) ||
(mstp_port->This_Station ==
MSTP_BROADCAST_ADDRESS)) {
if (MSTP_Frame_For_Us(mstp_port)) {
if (mstp_port->DataLength <=
mstp_port->InputBufferSize) {
/* Data */
Expand All @@ -467,7 +470,7 @@ void MSTP_Receive_Frame_FSM(struct mstp_port_struct_t *mstp_port)
MSTP_RECEIVE_STATE_SKIP_DATA;
}
} else {
/* NotForUs */
/* DataNotForUs */
mstp_port->receive_state =
MSTP_RECEIVE_STATE_SKIP_DATA;
}
Expand Down Expand Up @@ -560,18 +563,28 @@ void MSTP_Receive_Frame_FSM(struct mstp_port_struct_t *mstp_port)
&mstp_port->InputBuffer[mstp_port->Index + 1],
mstp_port->InputBufferSize, mstp_port->InputBuffer,
mstp_port->Index + 1);
if (mstp_port->DataLength > 0) {
if ((mstp_port->DataLength > 0) &&
(mstp_port->receive_state ==
MSTP_RECEIVE_STATE_DATA)) {
/* GoodCRC */
mstp_port->ReceivedValidFrame = true;
} else {
/* Done */
mstp_port->ReceivedInvalidFrame = true;
}
} else {
/* STATE DATA CRC - no need for new state */
if (mstp_port->DataCRC == 0xF0B8) {
/* indicate the complete reception of a
valid frame */
mstp_port->ReceivedValidFrame = true;
if (mstp_port->receive_state ==
MSTP_RECEIVE_STATE_DATA) {
/* GoodCRC */
mstp_port->ReceivedValidFrame = true;
} else {
/* Done */
mstp_port->ReceivedInvalidFrame = true;
}
} else {
/* BadCRC */
mstp_port->ReceivedInvalidFrame = true;
printf_receive_error(
"MSTP: Rx Data: BadCRC [%02X]\n",
Expand Down Expand Up @@ -623,28 +636,16 @@ bool MSTP_Master_Node_FSM(struct mstp_port_struct_t *mstp_port)
(mstp_port->This_Station + 1) % (mstp_port->Nmax_master + 1);
next_next_station =
(mstp_port->Next_Station + 1) % (mstp_port->Nmax_master + 1);
/* The zero config receive state machine does not
filter DestinationAddress for This_Station or Broadcast.
Check before running FSM: */
if (mstp_port->ReceivedValidFrame == true) {
if ((mstp_port->master_state == MSTP_MASTER_STATE_INITIALIZE) &&
(mstp_port->ZeroConfigEnabled)) {
/* zero config initialization processes all frames */
} else {
if ((mstp_port->DestinationAddress == mstp_port->This_Station) ||
(mstp_port->DestinationAddress == MSTP_BROADCAST_ADDRESS)) {
/* process as-is */
} else {
if ((mstp_port->ZeroConfigEnabled) &&
(mstp_port->SourceAddress == mstp_port->This_Station)) {
/* DuplicateNode */
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_INIT;
mstp_port->master_state = MSTP_MASTER_STATE_INITIALIZE;
}
/* ignore the frame */
mstp_port->ReceivedValidFrame = false;
}
}
/* The zero config checks before running FSM */
if ((mstp_port->ZeroConfigEnabled) &&
(mstp_port->master_state != MSTP_MASTER_STATE_INITIALIZE) &&
(mstp_port->ReceivedValidFrame == true) &&
(mstp_port->SourceAddress == mstp_port->This_Station)) {
/* DuplicateNode */
mstp_port->Zero_Config_State = MSTP_ZERO_CONFIG_STATE_INIT;
mstp_port->master_state = MSTP_MASTER_STATE_INITIALIZE;
/* ignore the frame */
mstp_port->ReceivedValidFrame = false;
}
switch (mstp_port->master_state) {
case MSTP_MASTER_STATE_INITIALIZE:
Expand Down

0 comments on commit ac7dee0

Please sign in to comment.