bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA * rd_data) { bool status = false; if (characterstring_ansi_same(&rd_data->password, "filister")) { Reinitialize_State = rd_data->state; dcc_set_status_duration(COMMUNICATION_ENABLE, 0); /* Note: you could use a mix of state and password to multiple things */ /* note: you probably want to restart *after* the simple ack has been sent from the return handler so just set a flag from here */ status = true; } else { rd_data->error_class = ERROR_CLASS_SECURITY; rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; } return status; }
/** Handler for a Device Communication Control (DCC) request. * @ingroup DMDCC * This handler will be invoked by apdu_handler() if it has been enabled * by a call to apdu_set_confirmed_handler(). * This handler builds a response packet, which is * - an Abort if * - the message is segmented * - if decoding fails * - if not a known DCC state * - an Error if the DCC password is incorrect * - else tries to send a simple ACK for the DCC on success, * and sets the DCC state requested. * * @param service_request [in] The contents of the service request. * @param service_len [in] The length of the service_request. * @param src [in] BACNET_ADDRESS of the source of the message * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information * decoded from the APDU header of this message. */ void handler_device_communication_control( uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data) { uint16_t timeDuration = 0; BACNET_COMMUNICATION_ENABLE_DISABLE state = COMMUNICATION_ENABLE; BACNET_CHARACTER_STRING password; int len = 0; int pdu_len = 0; BACNET_NPDU_DATA npdu_data; BACNET_ADDRESS my_address; /* encode the NPDU portion of the reply packet */ datalink_get_my_address(&my_address); npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address, &npdu_data); #if PRINT_ENABLED fprintf(stderr, "DeviceCommunicationControl!\n"); #endif if (service_data->segmented_message) { len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); #if PRINT_ENABLED fprintf(stderr, "DeviceCommunicationControl: " "Sending Abort - segmented message.\n"); #endif goto DCC_ABORT; } /* decode the service request only */ len = dcc_decode_service_request(service_request, service_len, &timeDuration, &state, &password); #if PRINT_ENABLED if (len > 0) fprintf(stderr, "DeviceCommunicationControl: " "timeout=%u state=%u password=%s\n", (unsigned) timeDuration, (unsigned) state, characterstring_value(&password)); #endif /* bad decoding or something we didn't understand - send an abort */ if (len < 0) { len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_OTHER, true); #if PRINT_ENABLED fprintf(stderr, "DeviceCommunicationControl: " "Sending Abort - could not decode.\n"); #endif goto DCC_ABORT; } if (state >= MAX_BACNET_COMMUNICATION_ENABLE_DISABLE) { len = reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION); #if PRINT_ENABLED fprintf(stderr, "DeviceCommunicationControl: " "Sending Reject - undefined enumeration\n"); #endif } else { #if BAC_ROUTING /* Check to see if the current Device supports this service. */ len = Routed_Device_Service_Approval (SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL, (int) state, &Handler_Transmit_Buffer[pdu_len], service_data->invoke_id); if (len > 0) goto DCC_ABORT; #endif if (characterstring_ansi_same(&password, My_Password)) { len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL); #if PRINT_ENABLED fprintf(stderr, "DeviceCommunicationControl: " "Sending Simple Ack!\n"); #endif dcc_set_status_duration(state, timeDuration); } else { len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL, ERROR_CLASS_SECURITY, ERROR_CODE_PASSWORD_FAILURE); #if PRINT_ENABLED fprintf(stderr, "DeviceCommunicationControl: " "Sending Error - password failure.\n"); #endif } } DCC_ABORT: pdu_len += len; len = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); if (len <= 0) { #if PRINT_ENABLED fprintf(stderr, "DeviceCommunicationControl: " "Failed to send PDU (%s)!\n", strerror(errno)); #endif } return; }