Ignore ReinitializeDevice and DeviceCommunicationControl service password (#518)

* Fix device object ReinitializeDevice service handling examples of no-password in the device. Add unit testing of device object ReinitializeDevice service.  Add API for setting ReinitializeDevice device object password.

* Fix DeviceCommunicationControl service handling example of no-password in the device.

---------

Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
Steve Karg
2023-10-18 21:32:44 -05:00
committed by GitHub
parent e143066b29
commit 0b5474d36e
12 changed files with 576 additions and 173 deletions
+51 -32
View File
@@ -74,8 +74,8 @@ static object_functions_t My_Object_Table[] = {
Device_Property_Lists, DeviceGetRRInfo, NULL /* Iterator */,
NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */,
NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */,
NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */,
NULL /* Timer */ },
#if (BACNET_PROTOCOL_REVISION >= 17)
{ OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
@@ -93,7 +93,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */ },
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
#if (BACNET_PROTOCOL_REVISION >= 14)
{ OBJECT_LIGHTING_OUTPUT, Lighting_Output_Init, Lighting_Output_Count,
Lighting_Output_Index_To_Instance, Lighting_Output_Valid_Instance,
@@ -102,14 +102,14 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Lighting_Output_Create, Lighting_Output_Delete, Lighting_Output_Timer},
Lighting_Output_Create, Lighting_Output_Delete, Lighting_Output_Timer },
{ OBJECT_CHANNEL, Channel_Init, Channel_Count, Channel_Index_To_Instance,
Channel_Valid_Instance, Channel_Object_Name, Channel_Read_Property,
Channel_Write_Property, Channel_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Channel_Create, Channel_Delete, NULL /* Timer */ },
Channel_Create, Channel_Delete, NULL /* Timer */ },
#endif
#if (BACNET_PROTOCOL_REVISION >= 24)
{ OBJECT_COLOR, Color_Init, Color_Count, Color_Index_To_Instance,
@@ -118,7 +118,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Color_Create, Color_Delete, Color_Timer},
Color_Create, Color_Delete, Color_Timer },
{ OBJECT_COLOR_TEMPERATURE, Color_Temperature_Init, Color_Temperature_Count,
Color_Temperature_Index_To_Instance, Color_Temperature_Valid_Instance,
Color_Temperature_Object_Name, Color_Temperature_Read_Property,
@@ -127,7 +127,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Color_Temperature_Create, Color_Temperature_Delete,
Color_Temperature_Timer},
Color_Temperature_Timer },
#endif
{ MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */,
NULL /* Index_To_Instance */, NULL /* Valid_Instance */,
@@ -136,7 +136,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }
};
/** Glue function to let the Device object, when called by a handler,
@@ -329,6 +329,24 @@ static uint32_t Database_Revision = 0;
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
static const char *Reinit_Password = "filister";
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/** Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
@@ -345,6 +363,7 @@ static const char *Reinit_Password = "filister";
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{
bool status = false;
bool password_success = false;
/* From 16.4.1.1.2 Password
This optional parameter shall be a CharacterString of up to
@@ -352,12 +371,21 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) {
/* Note: you could use a mix of state and password to
accomplish multiple things before restarting */
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) {
case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART:
@@ -387,9 +415,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break;
}
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
return status;
@@ -1103,9 +1128,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
apdu_len = bacnet_array_encode(rpdata->object_instance,
rpdata->array_index,
Device_Object_List_Element_Encode,
count, apdu, apdu_max);
rpdata->array_index, Device_Object_List_Element_Encode, count,
apdu, apdu_max);
if (apdu_len == BACNET_STATUS_ABORT) {
rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
@@ -1635,8 +1659,8 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
}
#endif
if (wp_data->object_property == PROP_OBJECT_NAME) {
status = Device_Write_Property_Object_Name(wp_data,
pObject->Object_Write_Property);
status = Device_Write_Property_Object_Name(
wp_data, pObject->Object_Write_Property);
} else {
status = pObject->Object_Write_Property(wp_data);
}
@@ -1663,8 +1687,7 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
* @return The length of the apdu encoded or #BACNET_STATUS_ERROR or
* #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT.
*/
int Device_Add_List_Element(
BACNET_LIST_ELEMENT_DATA * list_element)
int Device_Add_List_Element(BACNET_LIST_ELEMENT_DATA *list_element)
{
int status = BACNET_STATUS_ERROR;
struct object_functions *pObject = NULL;
@@ -1698,8 +1721,7 @@ int Device_Add_List_Element(
* @return The length of the apdu encoded or #BACNET_STATUS_ERROR or
* #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT.
*/
int Device_Remove_List_Element(
BACNET_LIST_ELEMENT_DATA * list_element)
int Device_Remove_List_Element(BACNET_LIST_ELEMENT_DATA *list_element)
{
int status = BACNET_STATUS_ERROR;
struct object_functions *pObject = NULL;
@@ -1805,8 +1827,7 @@ void Device_COV_Clear(BACNET_OBJECT_TYPE object_type, uint32_t object_instance)
* @param data - CreateObject data, including error codes if failures
* @return true if object has been created
*/
bool Device_Create_Object(
BACNET_CREATE_OBJECT_DATA *data)
bool Device_Create_Object(BACNET_CREATE_OBJECT_DATA *data)
{
bool status = false;
struct object_functions *pObject = NULL;
@@ -1865,8 +1886,7 @@ bool Device_Create_Object(
* @param data - DeleteObject data, including error codes if failures
* @return true if object has been deleted
*/
bool Device_Delete_Object(
BACNET_DELETE_OBJECT_DATA *data)
bool Device_Delete_Object(BACNET_DELETE_OBJECT_DATA *data)
{
bool status = false;
struct object_functions *pObject = NULL;
@@ -1997,8 +2017,7 @@ bool DeviceGetRRInfo(BACNET_READ_RANGE_DATA *pRequest, /* Info on the request */
* @brief Updates all the object timers with elapsed milliseconds
* @param milliseconds - number of milliseconds elapsed
*/
void Device_Timer(
uint16_t milliseconds)
void Device_Timer(uint16_t milliseconds)
{
struct object_functions *pObject;
unsigned count = 0;
+47 -24
View File
@@ -67,8 +67,8 @@ static object_functions_t My_Object_Table[] = {
Device_Property_Lists, DeviceGetRRInfo, NULL /* Iterator */,
NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */,
NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */,
NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */,
NULL /* Timer */ },
#if (BACNET_PROTOCOL_REVISION >= 17)
{ OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
@@ -95,7 +95,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Binary_Output_Create, Binary_Output_Delete, NULL /* Timer */},
Binary_Output_Create, Binary_Output_Delete, NULL /* Timer */ },
{ MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */,
NULL /* Index_To_Instance */, NULL /* Valid_Instance */,
NULL /* Object_Name */, NULL /* Read_Property */,
@@ -103,7 +103,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }
};
/** Glue function to let the Device object, when called by a handler,
@@ -296,6 +296,24 @@ static uint32_t Database_Revision = 0;
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
static const char *Reinit_Password = "raspberry";
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/** Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
@@ -312,6 +330,7 @@ static const char *Reinit_Password = "raspberry";
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{
bool status = false;
bool password_success = false;
/* From 16.4.1.1.2 Password
This optional parameter shall be a CharacterString of up to
@@ -319,12 +338,21 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) {
/* Note: you could use a mix of state and password to
accomplish multiple things before restarting */
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) {
case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART:
@@ -1070,9 +1098,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
apdu_len = bacnet_array_encode(rpdata->object_instance,
rpdata->array_index,
Device_Object_List_Element_Encode,
count, apdu, apdu_max);
rpdata->array_index, Device_Object_List_Element_Encode, count,
apdu, apdu_max);
if (apdu_len == BACNET_STATUS_ABORT) {
rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
@@ -1230,7 +1257,7 @@ int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
} else {
rpdata->error_class = ERROR_CLASS_OBJECT;
rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
}
} else {
rpdata->error_class = ERROR_CLASS_OBJECT;
rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT;
@@ -1602,8 +1629,8 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
}
#endif
if (wp_data->object_property == PROP_OBJECT_NAME) {
status = Device_Write_Property_Object_Name(wp_data,
pObject->Object_Write_Property);
status = Device_Write_Property_Object_Name(
wp_data, pObject->Object_Write_Property);
} else {
status = pObject->Object_Write_Property(wp_data);
}
@@ -1630,8 +1657,7 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
* @return The length of the apdu encoded or #BACNET_STATUS_ERROR or
* #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT.
*/
int Device_Add_List_Element(
BACNET_LIST_ELEMENT_DATA * list_element)
int Device_Add_List_Element(BACNET_LIST_ELEMENT_DATA *list_element)
{
int status = BACNET_STATUS_ERROR;
struct object_functions *pObject = NULL;
@@ -1665,8 +1691,7 @@ int Device_Add_List_Element(
* @return The length of the apdu encoded or #BACNET_STATUS_ERROR or
* #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT.
*/
int Device_Remove_List_Element(
BACNET_LIST_ELEMENT_DATA * list_element)
int Device_Remove_List_Element(BACNET_LIST_ELEMENT_DATA *list_element)
{
int status = BACNET_STATUS_ERROR;
struct object_functions *pObject = NULL;
@@ -1772,8 +1797,7 @@ void Device_COV_Clear(BACNET_OBJECT_TYPE object_type, uint32_t object_instance)
* @param data - CreateObject data, including error codes if failures
* @return true if object has been created
*/
bool Device_Create_Object(
BACNET_CREATE_OBJECT_DATA *data)
bool Device_Create_Object(BACNET_CREATE_OBJECT_DATA *data)
{
bool status = false;
struct object_functions *pObject = NULL;
@@ -1832,8 +1856,7 @@ bool Device_Create_Object(
* @param data - DeleteObject data, including error codes if failures
* @return true if object has been deleted
*/
bool Device_Delete_Object(
BACNET_DELETE_OBJECT_DATA *data)
bool Device_Delete_Object(BACNET_DELETE_OBJECT_DATA *data)
{
bool status = false;
struct object_functions *pObject = NULL;
+65 -21
View File
@@ -67,12 +67,11 @@ static struct my_object_functions {
read_property_function Object_Read_Property;
write_property_function Object_Write_Property;
rpm_property_lists_function Object_RPM_List;
} Object_Table[] = {
{ OBJECT_DEVICE, NULL, /* don't init - recursive! */
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists },
} Object_Table[] = { { OBJECT_DEVICE, NULL, /* don't init - recursive! */
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists },
{ OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
Analog_Input_Object_Name, Analog_Input_Read_Property, NULL,
@@ -159,8 +158,7 @@ static int Read_Property_Common(
}
apdu = rpdata->application_data;
if (property_list_common(rpdata->object_property)) {
apdu_len = property_list_common_encode(rpdata,
Object_Instance_Number);
apdu_len = property_list_common_encode(rpdata, Object_Instance_Number);
} else if (rpdata->object_property == PROP_OBJECT_NAME) {
/* only array properties can have array options */
if (rpdata->array_index != BACNET_ARRAY_ALL) {
@@ -180,9 +178,8 @@ static int Read_Property_Common(
} else if (rpdata->object_property == PROP_PROPERTY_LIST) {
Device_Objects_Property_List(
rpdata->object_type, rpdata->object_instance, &property_list);
apdu_len = property_list_encode(rpdata,
property_list.Required.pList, property_list.Optional.pList,
property_list.Proprietary.pList);
apdu_len = property_list_encode(rpdata, property_list.Required.pList,
property_list.Optional.pList, property_list.Proprietary.pList);
#endif
} else if (pObject->Object_Read_Property) {
apdu_len = pObject->Object_Read_Property(rpdata);
@@ -332,12 +329,64 @@ bool Device_Set_Object_Name(BACNET_CHARACTER_STRING *object_name)
return status;
}
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/**
* @brief Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
* actually *DO* anything.
* @note You could use a mix of states and passwords to multiple outcomes.
* @note You probably want to restart *after* the simple ack has been sent
* from the return handler, so just set a local flag here.
* @ingroup ObjIntf
*
* @param rd_data [in,out] The information from the RD request.
* On failure, the error class and code will be set.
* @return True if succeeds (password is correct), else False.
*/
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{
bool status = false;
bool password_success = false;
/* Note: you could use a mix of state and password to multiple things */
if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) {
/* From 16.4.1.1.2 Password
This optional parameter shall be a CharacterString of up to
20 characters. For those devices that require the password as a
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) {
case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART:
@@ -367,9 +416,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break;
}
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
return status;
@@ -705,9 +751,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
apdu_len = bacnet_array_encode(rpdata->object_instance,
rpdata->array_index,
Device_Object_List_Element_Encode,
count, apdu, apdu_max);
rpdata->array_index, Device_Object_List_Element_Encode, count,
apdu, apdu_max);
if (apdu_len == BACNET_STATUS_ABORT) {
rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
@@ -745,8 +790,7 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
encode_application_unsigned(&apdu[0], dlmstp_max_master());
break;
case 9600:
apdu_len =
encode_application_unsigned(&apdu[0], rs485_baud_rate());
apdu_len = encode_application_unsigned(&apdu[0], rs485_baud_rate());
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
+62 -16
View File
@@ -67,12 +67,11 @@ static struct my_object_functions {
read_property_function Object_Read_Property;
write_property_function Object_Write_Property;
rpm_property_lists_function Object_RPM_List;
} Object_Table[] = {
{ OBJECT_DEVICE, NULL, /* don't init - recursive! */
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists },
} Object_Table[] = { { OBJECT_DEVICE, NULL, /* don't init - recursive! */
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists },
{ OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
Analog_Input_Object_Name, Analog_Input_Read_Property, NULL,
@@ -161,8 +160,7 @@ int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
#if (BACNET_PROTOCOL_REVISION >= 14)
if ((int)rpdata->object_property == PROP_PROPERTY_LIST) {
Device_Objects_Property_List(rpdata->object_type,
rpdata->object_instance,
&property_list);
rpdata->object_instance, &property_list);
apdu_len = property_list_encode(rpdata,
property_list.Required.pList,
property_list.Optional.pList,
@@ -306,12 +304,64 @@ bool Device_Object_Name(
return status;
}
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/**
* @brief Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
* actually *DO* anything.
* @note You could use a mix of states and passwords to multiple outcomes.
* @note You probably want to restart *after* the simple ack has been sent
* from the return handler, so just set a local flag here.
* @ingroup ObjIntf
*
* @param rd_data [in,out] The information from the RD request.
* On failure, the error class and code will be set.
* @return True if succeeds (password is correct), else False.
*/
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{
bool status = false;
bool password_success = false;
/* Note: you could use a mix of state and password to multiple things */
if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) {
/* From 16.4.1.1.2 Password
This optional parameter shall be a CharacterString of up to
20 characters. For those devices that require the password as a
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) {
case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART:
@@ -341,9 +391,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break;
}
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
return status;
@@ -695,9 +742,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
apdu_len = bacnet_array_encode(rpdata->object_instance,
rpdata->array_index,
Device_Object_List_Element_Encode,
count, apdu, apdu_max);
rpdata->array_index, Device_Object_List_Element_Encode, count,
apdu, apdu_max);
if (apdu_len == BACNET_STATUS_ABORT) {
rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
+54 -6
View File
@@ -52,14 +52,65 @@ static uint32_t Object_Instance_Number = 12345;
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
static uint8_t Database_Revision;
BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
static char Reinit_Password[16] = "filister";
static const char *Reinit_Password = "filister";
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/** Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
* actually *DO* anything.
* @note You could use a mix of states and passwords to multiple outcomes.
* @note You probably want to restart *after* the simple ack has been sent
* from the return handler, so just set a local flag here.
* @ingroup ObjIntf
*
* @param rd_data [in,out] The information from the RD request.
* On failure, the error class and code will be set.
* @return True if succeeds (password is correct), else False.
*/
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{
bool status = false;
bool password_success = false;
/* Note: you could use a mix of state and password to multiple things */
if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) {
/* From 16.4.1.1.2 Password
This optional parameter shall be a CharacterString of up to
20 characters. For those devices that require the password as a
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) {
case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART:
@@ -89,9 +140,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break;
}
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
return status;
+54 -5
View File
@@ -271,12 +271,64 @@ uint32_t Device_Index_To_Instance(unsigned index)
return Object_Instance_Number;
}
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/**
* @brief Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
* actually *DO* anything.
* @note You could use a mix of states and passwords to multiple outcomes.
* @note You probably want to restart *after* the simple ack has been sent
* from the return handler, so just set a local flag here.
* @ingroup ObjIntf
*
* @param rd_data [in,out] The information from the RD request.
* On failure, the error class and code will be set.
* @return True if succeeds (password is correct), else False.
*/
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{
bool status = false;
bool password_success = false;
/* Note: you could use a mix of state and password to multiple things */
if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) {
/* From 16.4.1.1.2 Password
This optional parameter shall be a CharacterString of up to
20 characters. For those devices that require the password as a
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) {
case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART:
@@ -306,9 +358,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break;
}
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
return status;
+54 -5
View File
@@ -342,12 +342,64 @@ bool Device_Set_Object_Name(BACNET_CHARACTER_STRING *object_name)
return status;
}
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/**
* @brief Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
* actually *DO* anything.
* @note You could use a mix of states and passwords to multiple outcomes.
* @note You probably want to restart *after* the simple ack has been sent
* from the return handler, so just set a local flag here.
* @ingroup ObjIntf
*
* @param rd_data [in,out] The information from the RD request.
* On failure, the error class and code will be set.
* @return True if succeeds (password is correct), else False.
*/
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{
bool status = false;
bool password_success = false;
/* Note: you could use a mix of state and password to multiple things */
if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) {
/* From 16.4.1.1.2 Password
This optional parameter shall be a CharacterString of up to
20 characters. For those devices that require the password as a
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) {
case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART:
@@ -379,9 +431,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break;
}
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
return status;
+54 -5
View File
@@ -336,12 +336,64 @@ bool Device_Set_Object_Name(BACNET_CHARACTER_STRING *object_name)
return status;
}
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/**
* @brief Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
* actually *DO* anything.
* @note You could use a mix of states and passwords to multiple outcomes.
* @note You probably want to restart *after* the simple ack has been sent
* from the return handler, so just set a local flag here.
* @ingroup ObjIntf
*
* @param rd_data [in,out] The information from the RD request.
* On failure, the error class and code will be set.
* @return True if succeeds (password is correct), else False.
*/
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{
bool status = false;
bool password_success = false;
/* Note: you could use a mix of state and password to multiple things */
if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) {
/* From 16.4.1.1.2 Password
This optional parameter shall be a CharacterString of up to
20 characters. For those devices that require the password as a
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) {
case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART:
@@ -373,9 +425,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break;
}
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
return status;
+66 -47
View File
@@ -98,8 +98,8 @@ static object_functions_t My_Object_Table[] = {
Device_Property_Lists, DeviceGetRRInfo, NULL /* Iterator */,
NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */,
NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */,
NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */,
NULL /* Timer */ },
#if (BACNET_PROTOCOL_REVISION >= 17)
{ OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
@@ -108,7 +108,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */},
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
#endif
{ OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
@@ -118,7 +118,7 @@ static object_functions_t My_Object_Table[] = {
Analog_Input_Encode_Value_List, Analog_Input_Change_Of_Value,
Analog_Input_Change_Of_Value_Clear, Analog_Input_Intrinsic_Reporting,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */},
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
{ OBJECT_ANALOG_OUTPUT, Analog_Output_Init, Analog_Output_Count,
Analog_Output_Index_To_Instance, Analog_Output_Valid_Instance,
Analog_Output_Object_Name, Analog_Output_Read_Property,
@@ -126,7 +126,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Analog_Output_Create, Analog_Output_Delete, NULL /* Timer */},
Analog_Output_Create, Analog_Output_Delete, NULL /* Timer */ },
{ OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count,
Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance,
Analog_Value_Object_Name, Analog_Value_Read_Property,
@@ -152,7 +152,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Binary_Output_Create, Binary_Output_Delete, NULL /* Timer */},
Binary_Output_Create, Binary_Output_Delete, NULL /* Timer */ },
{ OBJECT_BINARY_VALUE, Binary_Value_Init, Binary_Value_Count,
Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance,
Binary_Value_Object_Name, Binary_Value_Read_Property,
@@ -171,8 +171,8 @@ static object_functions_t My_Object_Table[] = {
CharacterString_Value_Change_Of_Value,
CharacterString_Value_Change_Of_Value_Clear,
NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */,
NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */,
NULL /* Timer */ },
{ OBJECT_COMMAND, Command_Init, Command_Count, Command_Index_To_Instance,
Command_Valid_Instance, Command_Object_Name, Command_Read_Property,
Command_Write_Property, Command_Property_Lists,
@@ -197,8 +197,8 @@ static object_functions_t My_Object_Table[] = {
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
Notification_Class_Add_List_Element,
Notification_Class_Remove_List_Element,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
Notification_Class_Remove_List_Element, NULL /* Create */,
NULL /* Delete */, NULL /* Timer */ },
#endif
{ OBJECT_LIFE_SAFETY_POINT, Life_Safety_Point_Init, Life_Safety_Point_Count,
Life_Safety_Point_Index_To_Instance, Life_Safety_Point_Valid_Instance,
@@ -207,7 +207,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */},
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
{ OBJECT_LOAD_CONTROL, Load_Control_Init, Load_Control_Count,
Load_Control_Index_To_Instance, Load_Control_Valid_Instance,
Load_Control_Object_Name, Load_Control_Read_Property,
@@ -215,7 +215,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */},
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
{ OBJECT_MULTI_STATE_INPUT, Multistate_Input_Init, Multistate_Input_Count,
Multistate_Input_Index_To_Instance, Multistate_Input_Valid_Instance,
Multistate_Input_Object_Name, Multistate_Input_Read_Property,
@@ -223,7 +223,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */},
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
{ OBJECT_MULTI_STATE_OUTPUT, Multistate_Output_Init,
Multistate_Output_Count, Multistate_Output_Index_To_Instance,
Multistate_Output_Valid_Instance, Multistate_Output_Object_Name,
@@ -232,7 +232,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Multistate_Output_Create, Multistate_Output_Delete, NULL /* Timer */},
Multistate_Output_Create, Multistate_Output_Delete, NULL /* Timer */ },
{ OBJECT_MULTI_STATE_VALUE, Multistate_Value_Init, Multistate_Value_Count,
Multistate_Value_Index_To_Instance, Multistate_Value_Valid_Instance,
Multistate_Value_Object_Name, Multistate_Value_Read_Property,
@@ -241,7 +241,7 @@ static object_functions_t My_Object_Table[] = {
Multistate_Value_Encode_Value_List, Multistate_Value_Change_Of_Value,
Multistate_Value_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */},
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
{ OBJECT_TRENDLOG, Trend_Log_Init, Trend_Log_Count,
Trend_Log_Index_To_Instance, Trend_Log_Valid_Instance,
Trend_Log_Object_Name, Trend_Log_Read_Property,
@@ -249,7 +249,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */},
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
#if (BACNET_PROTOCOL_REVISION >= 14)
{ OBJECT_LIGHTING_OUTPUT, Lighting_Output_Init, Lighting_Output_Count,
Lighting_Output_Index_To_Instance, Lighting_Output_Valid_Instance,
@@ -258,7 +258,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Lighting_Output_Create, Lighting_Output_Delete, Lighting_Output_Timer},
Lighting_Output_Create, Lighting_Output_Delete, Lighting_Output_Timer },
{ OBJECT_CHANNEL, Channel_Init, Channel_Count, Channel_Index_To_Instance,
Channel_Valid_Instance, Channel_Object_Name, Channel_Read_Property,
Channel_Write_Property, Channel_Property_Lists,
@@ -274,7 +274,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Color_Create, Color_Delete, Color_Timer},
Color_Create, Color_Delete, Color_Timer },
{ OBJECT_COLOR_TEMPERATURE, Color_Temperature_Init, Color_Temperature_Count,
Color_Temperature_Index_To_Instance, Color_Temperature_Valid_Instance,
Color_Temperature_Object_Name, Color_Temperature_Read_Property,
@@ -283,7 +283,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Color_Temperature_Create, Color_Temperature_Delete,
Color_Temperature_Timer},
Color_Temperature_Timer },
#endif
#if defined(BACFILE)
{ OBJECT_FILE, bacfile_init, bacfile_count, bacfile_index_to_instance,
@@ -292,7 +292,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
bacfile_create, bacfile_delete, NULL /* Timer */},
bacfile_create, bacfile_delete, NULL /* Timer */ },
#endif
{ OBJECT_OCTETSTRING_VALUE, OctetString_Value_Init, OctetString_Value_Count,
OctetString_Value_Index_To_Instance, OctetString_Value_Valid_Instance,
@@ -318,8 +318,8 @@ static object_functions_t My_Object_Table[] = {
Schedule_Property_Lists, NULL /* ReadRangeInfo */, NULL /* Iterator */,
NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */,
NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */,
NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */,
NULL /* Timer */ },
{ OBJECT_ACCUMULATOR, Accumulator_Init, Accumulator_Count,
Accumulator_Index_To_Instance, Accumulator_Valid_Instance,
Accumulator_Object_Name, Accumulator_Read_Property,
@@ -327,7 +327,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */ , NULL /* Timer */},
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
{ MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */,
NULL /* Index_To_Instance */, NULL /* Valid_Instance */,
NULL /* Object_Name */, NULL /* Read_Property */,
@@ -528,6 +528,24 @@ static uint32_t Database_Revision = 0;
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
static const char *Reinit_Password = "filister";
/**
* @brief Sets the ReinitializeDevice password
*
* The password shall be a null terminated C string of up to
* 20 ASCII characters for those devices that require the password.
*
* For those devices that do not require a password, set to NULL or
* point to a zero length C string (null terminated).
*
* @param the ReinitializeDevice password; can be NULL or empty string
*/
bool Device_Reinitialize_Password_Set(const char *password)
{
Reinit_Password = password;
return true;
}
/** Commands a Device re-initialization, to a given state.
* The request's password must match for the operation to succeed.
* This implementation provides a framework, but doesn't
@@ -544,6 +562,7 @@ static const char *Reinit_Password = "filister";
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
{
bool status = false;
bool password_success = false;
/* From 16.4.1.1.2 Password
This optional parameter shall be a CharacterString of up to
@@ -551,12 +570,21 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
protection, the service request shall be denied if the parameter
is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) {
/* Note: you could use a mix of state and password to
accomplish multiple things before restarting */
if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
&rd_data->password, Reinit_Password)) {
password_success = true;
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
} else {
password_success = true;
}
if (password_success) {
switch (rd_data->state) {
case BACNET_REINIT_COLDSTART:
case BACNET_REINIT_WARMSTART:
@@ -586,9 +614,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
break;
}
} else {
rd_data->error_class = ERROR_CLASS_SECURITY;
rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE;
}
return status;
@@ -1306,9 +1331,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
apdu_len = bacnet_array_encode(rpdata->object_instance,
rpdata->array_index,
Device_Object_List_Element_Encode,
count, apdu, apdu_max);
rpdata->array_index, Device_Object_List_Element_Encode, count,
apdu, apdu_max);
if (apdu_len == BACNET_STATUS_ABORT) {
rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
@@ -1838,8 +1862,8 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
}
#endif
if (wp_data->object_property == PROP_OBJECT_NAME) {
status = Device_Write_Property_Object_Name(wp_data,
pObject->Object_Write_Property);
status = Device_Write_Property_Object_Name(
wp_data, pObject->Object_Write_Property);
} else {
status = pObject->Object_Write_Property(wp_data);
}
@@ -1866,8 +1890,7 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
* @return The length of the apdu encoded or #BACNET_STATUS_ERROR or
* #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT.
*/
int Device_Add_List_Element(
BACNET_LIST_ELEMENT_DATA * list_element)
int Device_Add_List_Element(BACNET_LIST_ELEMENT_DATA *list_element)
{
int status = BACNET_STATUS_ERROR;
struct object_functions *pObject = NULL;
@@ -1901,8 +1924,7 @@ int Device_Add_List_Element(
* @return The length of the apdu encoded or #BACNET_STATUS_ERROR or
* #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT.
*/
int Device_Remove_List_Element(
BACNET_LIST_ELEMENT_DATA * list_element)
int Device_Remove_List_Element(BACNET_LIST_ELEMENT_DATA *list_element)
{
int status = BACNET_STATUS_ERROR;
struct object_functions *pObject = NULL;
@@ -2008,8 +2030,7 @@ void Device_COV_Clear(BACNET_OBJECT_TYPE object_type, uint32_t object_instance)
* @param data - CreateObject data, including error codes if failures
* @return true if object has been created
*/
bool Device_Create_Object(
BACNET_CREATE_OBJECT_DATA *data)
bool Device_Create_Object(BACNET_CREATE_OBJECT_DATA *data)
{
bool status = false;
struct object_functions *pObject = NULL;
@@ -2068,8 +2089,7 @@ bool Device_Create_Object(
* @param data - DeleteObject data, including error codes if failures
* @return true if object has been deleted
*/
bool Device_Delete_Object(
BACNET_DELETE_OBJECT_DATA *data)
bool Device_Delete_Object(BACNET_DELETE_OBJECT_DATA *data)
{
bool status = false;
struct object_functions *pObject = NULL;
@@ -2236,8 +2256,7 @@ bool DeviceGetRRInfo(BACNET_READ_RANGE_DATA *pRequest, /* Info on the request */
* @brief Updates all the object timers with elapsed milliseconds
* @param milliseconds - number of milliseconds elapsed
*/
void Device_Timer(
uint16_t milliseconds)
void Device_Timer(uint16_t milliseconds)
{
struct object_functions *pObject;
unsigned count = 0;
+3
View File
@@ -254,6 +254,9 @@ extern "C" {
BACNET_STACK_EXPORT
BACNET_REINITIALIZED_STATE Device_Reinitialized_State(
void);
BACNET_STACK_EXPORT
bool Device_Reinitialize_Password_Set(
const char *password);
BACNET_STACK_EXPORT
rr_info_function Device_Objects_RR_Info(
+2 -2
View File
@@ -173,8 +173,8 @@ void handler_device_communication_control(uint8_t *service_request,
if (len > 0)
goto DCC_ABORT;
#endif
if (characterstring_ansi_same(&password, My_Password)) {
if ((My_Password[0] == '\0') ||
characterstring_ansi_same(&password, My_Password)) {
len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL);
+62 -8
View File
@@ -41,7 +41,8 @@ static void test_Device_Data_Sharing(void)
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_DEVICE;
rpdata.object_instance = Device_Index_To_Instance(0);;
rpdata.object_instance = Device_Index_To_Instance(0);
;
Device_Property_Lists(&pRequired, &pOptional, &pProprietary);
while ((*pRequired) != -1) {
rpdata.object_property = *pRequired;
@@ -49,7 +50,7 @@ static void test_Device_Data_Sharing(void)
len = Device_Read_Property(&rpdata);
zassert_not_equal(len, BACNET_STATUS_ERROR,
"property '%s': failed to ReadProperty!\n",
bactext_property_name(rpdata.object_property));
bactext_property_name(rpdata.object_property));
if (len > 0) {
test_len = bacapp_decode_application_data(rpdata.application_data,
(uint8_t)rpdata.application_data_len, &value);
@@ -85,7 +86,7 @@ static void test_Device_Data_Sharing(void)
len = Device_Read_Property(&rpdata);
zassert_not_equal(len, BACNET_STATUS_ERROR,
"property '%s': failed to ReadProperty!\n",
bactext_property_name(rpdata.object_property));
bactext_property_name(rpdata.object_property));
if (len > 0) {
test_len = bacapp_decode_application_data(rpdata.application_data,
(uint8_t)rpdata.application_data_len, &value);
@@ -127,6 +128,7 @@ static void testDevice(void)
{
bool status = false;
const char *name = "Patricia";
BACNET_REINITIALIZE_DEVICE_DATA rd_data;
status = Device_Set_Object_Instance_Number(0);
zassert_equal(Device_Object_Instance_Number(), 0, NULL);
@@ -151,22 +153,74 @@ static void testDevice(void)
Device_Set_Model_Name(name, strlen(name));
zassert_equal(strcmp(Device_Model_Name(), name), 0, NULL);
/* Reinitialize with no device password */
rd_data.error_class = ERROR_CLASS_DEVICE;
rd_data.error_code = ERROR_CODE_SUCCESS;
rd_data.state = BACNET_REINIT_COLDSTART;
characterstring_init_ansi(&rd_data.password, NULL);
status = Device_Reinitialize_Password_Set(NULL);
status = Device_Reinitialize(&rd_data);
zassert_true(status, NULL);
zassert_equal(rd_data.error_class, ERROR_CLASS_DEVICE, "error-class=%s",
bactext_error_class_name(rd_data.error_class));
zassert_equal(rd_data.error_code, ERROR_CODE_SUCCESS, "error-code=%s",
bactext_error_code_name(rd_data.error_code));
/* Reinitialize with device valid password, service no password */
status = Device_Reinitialize_Password_Set("valid");
zassert_true(status, NULL);
status = characterstring_init_ansi(&rd_data.password, NULL);
zassert_true(status, NULL);
status = Device_Reinitialize(&rd_data);
zassert_false(status, NULL);
zassert_equal(rd_data.error_class, ERROR_CLASS_SECURITY, "error-class=%s",
bactext_error_class_name(rd_data.error_class));
zassert_equal(rd_data.error_code, ERROR_CODE_PASSWORD_FAILURE,
"error-code=%s", bactext_error_code_name(rd_data.error_code));
/* Reinitialize with device valid password, service invalid password */
status = characterstring_init_ansi(&rd_data.password, "invalid");
zassert_true(status, NULL);
status = Device_Reinitialize(&rd_data);
zassert_false(status, NULL);
zassert_equal(rd_data.error_class, ERROR_CLASS_SECURITY, "error-class=%s",
bactext_error_class_name(rd_data.error_class));
zassert_equal(rd_data.error_code, ERROR_CODE_PASSWORD_FAILURE,
"error-code=%s", bactext_error_code_name(rd_data.error_code));
/* Reinitialize with device valid password, service valid password */
characterstring_init_ansi(&rd_data.password, "valid");
status = Device_Reinitialize(&rd_data);
zassert_true(status, NULL);
/* Reinitialize with device valid password, service too long password */
characterstring_init_ansi(&rd_data.password, "abcdefghijklmnopqrstuvwxyz");
status = Device_Reinitialize(&rd_data);
zassert_false(status, NULL);
zassert_equal(rd_data.error_class, ERROR_CLASS_SERVICES, "error-class=%s",
bactext_error_class_name(rd_data.error_class));
zassert_equal(rd_data.error_code, ERROR_CODE_PARAMETER_OUT_OF_RANGE,
"error-code=%s", bactext_error_code_name(rd_data.error_code));
/* Reinitialize with device no password, unsupported state */
status = Device_Reinitialize_Password_Set(NULL);
zassert_true(status, NULL);
rd_data.state = BACNET_REINIT_MAX;
status = Device_Reinitialize(&rd_data);
zassert_false(status, NULL);
zassert_equal(rd_data.error_class, ERROR_CLASS_SERVICES, "error-class=%s",
bactext_error_class_name(rd_data.error_class));
zassert_equal(rd_data.error_code, ERROR_CODE_PARAMETER_OUT_OF_RANGE,
"error-code=%s", bactext_error_code_name(rd_data.error_code));
return;
}
/**
* @}
*/
#if defined(CONFIG_ZTEST_NEW_API)
ZTEST_SUITE(device_tests, NULL, NULL, NULL, NULL, NULL);
#else
void test_main(void)
{
ztest_test_suite(device_tests,
ztest_unit_test(testDevice),
ztest_unit_test(test_Device_Data_Sharing)
);
ztest_test_suite(device_tests, ztest_unit_test(testDevice),
ztest_unit_test(test_Device_Data_Sharing));
ztest_run_test_suite(device_tests);
}