void testBinary_Value( Test * pTest) { uint8_t apdu[MAX_APDU] = { 0 }; int len = 0; uint32_t len_value = 0; uint8_t tag_number = 0; uint16_t decoded_type = 0; uint32_t decoded_instance = 0; BACNET_READ_PROPERTY_DATA rpdata; Binary_Value_Init(); rpdata.application_data = &apdu[0]; rpdata.application_data_len = sizeof(apdu); rpdata.object_type = OBJECT_BINARY_VALUE; rpdata.object_instance = 1; rpdata.object_property = PROP_OBJECT_IDENTIFIER; rpdata.array_index = BACNET_ARRAY_ALL; len = Binary_Value_Read_Property(&rpdata); ct_test(pTest, len != 0); len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value); ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID); len = decode_object_id(&apdu[len], &decoded_type, &decoded_instance); ct_test(pTest, decoded_type == rpdata.object_type); ct_test(pTest, decoded_instance == rpdata.object_instance); return; }
void testBinaryInput( Test * pTest) { uint8_t apdu[MAX_APDU] = { 0 }; int len = 0; uint32_t len_value = 0; uint8_t tag_number = 0; BACNET_OBJECT_TYPE decoded_type = OBJECT_BINARY_OUTPUT; uint32_t decoded_instance = 0; uint32_t instance = 123; BACNET_ERROR_CLASS error_class; BACNET_ERROR_CODE error_code; /* FIXME: we should do a lot more testing here... */ len = Binary_Input_Encode_Property_APDU(&apdu[0], instance, PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code); ct_test(pTest, len >= 0); len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value); ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID); len = decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance); ct_test(pTest, decoded_type == OBJECT_BINARY_INPUT); ct_test(pTest, decoded_instance == instance); return; }
void testAnalog_Value( Test * pTest) { uint8_t far apdu[MAX_APDU] = { 0 }; int len = 0; uint32_t len_value = 0; uint8_t tag_number = 0; BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_VALUE; uint32_t decoded_instance = 0; uint32_t instance = 123; BACNET_ERROR_CLASS error_class; BACNET_ERROR_CODE error_code; len = Analog_Value_Encode_Property_APDU(&apdu[0], instance, PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code); ct_test(pTest, len != 0); len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value); ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID); len = decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance); ct_test(pTest, decoded_type == OBJECT_ANALOG_VALUE); ct_test(pTest, decoded_instance == instance); return; }
/* decode the service request only */ int whohas_decode_service_request( uint8_t * apdu, unsigned apdu_len, BACNET_WHO_HAS_DATA * data) { int len = 0; uint8_t tag_number = 0; uint32_t len_value = 0; uint32_t decoded_value = 0; /* for decoding */ uint16_t decoded_type = 0; /* for decoding */ if (apdu_len && data) { /* optional limits - must be used as a pair */ if (decode_is_context_tag(&apdu[len], 0)) { len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len += decode_unsigned(&apdu[len], len_value, &decoded_value); if (decoded_value <= BACNET_MAX_INSTANCE) data->low_limit = decoded_value; if (!decode_is_context_tag(&apdu[len], 1)) return -1; len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len += decode_unsigned(&apdu[len], len_value, &decoded_value); if (decoded_value <= BACNET_MAX_INSTANCE) data->high_limit = decoded_value; } else { data->low_limit = -1; data->high_limit = -1; } /* object id */ if (decode_is_context_tag(&apdu[len], 2)) { data->object_name = false; len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len += decode_object_id(&apdu[len], &decoded_type, &data->object.identifier.instance); data->object.identifier.type = decoded_type; } /* object name */ else if (decode_is_context_tag(&apdu[len], 3)) { data->object_name = true; len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len += decode_character_string(&apdu[len], len_value, &data->object.name); } /* missing required parameters */ else return -1; } return len; }
/* decode the object portion of the service request only */ int rpm_ack_decode_object_id( uint8_t * apdu, unsigned apdu_len, BACNET_OBJECT_TYPE * object_type, uint32_t * object_instance) { unsigned len = 0; uint16_t type = 0; /* for decoding */ /* check for value pointers */ if (apdu && apdu_len && object_type && object_instance) { /* Tag 0: objectIdentifier */ if (!decode_is_context_tag(&apdu[len++], 0)) return -1; len += decode_object_id(&apdu[len], &type, object_instance); if (object_type) *object_type = (BACNET_OBJECT_TYPE) type; /* Tag 1: listOfResults */ if (!decode_is_opening_tag_number(&apdu[len], 1)) return -1; len++; /* opening tag is only one octet */ } return (int) len; }
/* decode the object portion of the service request only. Bails out if * tags are wrong or missing/incomplete */ int rpm_decode_object_id( uint8_t * apdu, unsigned apdu_len, BACNET_RPM_DATA * rpmdata) { unsigned len = 0; uint16_t type = 0; /* for decoding */ /* check for value pointers */ if (apdu && apdu_len && rpmdata) { if (apdu_len < 5) { /* Must be at least 2 tags and an object id */ rpmdata->error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER; return BACNET_STATUS_REJECT; } /* Tag 0: Object ID */ if (!decode_is_context_tag(&apdu[len++], 0)) { rpmdata->error_code = ERROR_CODE_REJECT_INVALID_TAG; return BACNET_STATUS_REJECT; } len += decode_object_id(&apdu[len], &type, &rpmdata->object_instance); rpmdata->object_type = (BACNET_OBJECT_TYPE) type; /* Tag 1: sequence of ReadAccessSpecification */ if (!decode_is_opening_tag_number(&apdu[len], 1)) { rpmdata->error_code = ERROR_CODE_REJECT_INVALID_TAG; return BACNET_STATUS_REJECT; } len++; /* opening tag is only one octet */ } return (int) len; }
int rp_ack_decode_service_request( uint8_t * apdu, int apdu_len, /* total length of the apdu */ BACNET_READ_PROPERTY_DATA * rpdata) { uint8_t tag_number = 0; uint32_t len_value_type = 0; int tag_len = 0; /* length of tag decode */ int len = 0; /* total length of decodes */ uint16_t object = 0; /* object type */ uint32_t property = 0; /* for decoding */ uint32_t array_value = 0; /* for decoding */ memset(prop_name,0,100); /* FIXME: check apdu_len against the len during decode */ /* Tag 0: Object ID */ if (!decode_is_context_tag(&apdu[0], 0)) return -1; len = 1; len += decode_object_id(&apdu[len], &object, &rpdata->object_instance); rpdata->object_type = (BACNET_OBJECT_TYPE) object; /* Tag 1: Property ID */ len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number != 1) return -1; len += decode_enumerated(&apdu[len], len_value_type, &property); rpdata->object_property = (BACNET_PROPERTY_ID) property; if(rpdata->object_property < PROP_EGRESS_ACTIVE) strcpy_s(prop_name,100,bacnet_property_names[rpdata->object_property ].pString); /* Tag 2: Optional Array Index */ tag_len = decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number == 2) { len += tag_len; len += decode_unsigned(&apdu[len], len_value_type, &array_value); rpdata->array_index = array_value; } else rpdata->array_index = BACNET_ARRAY_ALL; /* Tag 3: opening context tag */ if (decode_is_opening_tag_number(&apdu[len], 3)) { /* a tag number of 3 is not extended so only one octet */ len++; /* don't decode the application tag number or its data here */ rpdata->application_data = &apdu[len]; rpdata->application_data_len = apdu_len - len - 1 /*closing tag */ ; /* len includes the data and the closing tag */ len = apdu_len; } else { return -1; } return len; }
/* decode the service request only */ int ihave_decode_service_request( uint8_t * apdu, unsigned apdu_len, BACNET_I_HAVE_DATA * data) { int len = 0; uint8_t tag_number = 0; uint32_t len_value = 0; uint16_t decoded_type = 0; /* for decoding */ if (apdu_len && data) { /* deviceIdentifier */ len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID) { len += decode_object_id(&apdu[len], &decoded_type, &data->device_id.instance); data->device_id.type = decoded_type; } else return -1; /* objectIdentifier */ len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID) { len += decode_object_id(&apdu[len], &decoded_type, &data->object_id.instance); data->object_id.type = decoded_type; } else return -1; /* objectName */ len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); if (tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING) { len += decode_character_string(&apdu[len], len_value, &data->object_name); } else return -1; } else return -1; return len; }
void testReadPropertyAck( Test * pTest) { uint8_t apdu[480] = { 0 }; uint8_t apdu2[480] = { 0 }; int len = 0; int apdu_len = 0; uint8_t invoke_id = 1; uint8_t test_invoke_id = 0; BACNET_READ_PROPERTY_DATA rpdata; BACNET_READ_PROPERTY_DATA test_data; BACNET_OBJECT_TYPE object_type = OBJECT_DEVICE; uint32_t object_instance = 0; uint16_t object = 0; rpdata.object_type = OBJECT_DEVICE; rpdata.object_instance = 1; rpdata.object_property = PROP_OBJECT_IDENTIFIER; rpdata.array_index = BACNET_ARRAY_ALL; rpdata.application_data_len = encode_bacnet_object_id(&apdu2[0], rpdata.object_type, rpdata.object_instance); rpdata.application_data = &apdu2[0]; len = rp_ack_encode_apdu(&apdu[0], invoke_id, &rpdata); ct_test(pTest, len != 0); ct_test(pTest, len != -1); apdu_len = len; len = rp_ack_decode_apdu(&apdu[0], apdu_len, /* total length of the apdu */ &test_invoke_id, &test_data); ct_test(pTest, len != -1); ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, test_data.object_type == rpdata.object_type); ct_test(pTest, test_data.object_instance == rpdata.object_instance); ct_test(pTest, test_data.object_property == rpdata.object_property); ct_test(pTest, test_data.array_index == rpdata.array_index); ct_test(pTest, test_data.application_data_len == rpdata.application_data_len); /* since object property == object_id, decode the application data using the appropriate decode function */ len = decode_object_id(test_data.application_data, &object, &object_instance); object_type = object; ct_test(pTest, object_type == rpdata.object_type); ct_test(pTest, object_instance == rpdata.object_instance); }
/** Decoding for WritePropertyMultiple service, object ID. * @ingroup DSWPM * This handler will be invoked by write_property_multiple handler * if it has been enabled by a call to apdu_set_confirmed_handler(). * This function decodes only the first tagged entity, which is * an object identifier. This function will return an error if: * - the tag is not the right value * - the number of bytes is not enough to decode for this entity * - the subsequent tag number is incorrect * * @param apdu [in] The contents of the APDU buffer. * @param apdu_len [in] The length of the APDU buffer. * @param data [out] The BACNET_WRITE_PROPERTY_DATA structure * which will contain the reponse values or error. */ int wpm_decode_object_id( uint8_t * apdu, uint16_t apdu_len, BACNET_WRITE_PROPERTY_DATA * wp_data) { uint8_t tag_number = 0; uint32_t len_value = 0; uint32_t object_instance = 0; uint16_t object_type = 0; uint16_t len = 0; if (apdu && (apdu_len > 5) && wp_data) { /* Context tag 0 - Object ID */ len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); if ((tag_number == 0) && (apdu_len > len)) { apdu_len -= len; if (apdu_len >= 4) { len += decode_object_id(&apdu[len], &object_type, &object_instance); wp_data->object_type = object_type; wp_data->object_instance = object_instance; apdu_len -= len; } else { wp_data->error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER; return BACNET_STATUS_REJECT; } } else { wp_data->error_code = ERROR_CODE_REJECT_INVALID_TAG; return BACNET_STATUS_REJECT; } /* just test for the next tag - no need to decode it here */ /* Context tag 1: sequence of BACnetPropertyValue */ if (apdu_len && !decode_is_opening_tag_number(&apdu[len], 1)) { wp_data->error_code = ERROR_CODE_REJECT_INVALID_TAG; return BACNET_STATUS_REJECT; } } else { wp_data->error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER; return BACNET_STATUS_REJECT; } return (int) len; }
/* decode the service request only */ int arf_decode_service_request( uint8_t * apdu, unsigned apdu_len, BACNET_ATOMIC_READ_FILE_DATA * data) { int len = 0; int tag_len = 0; uint8_t tag_number = 0; uint32_t len_value_type = 0; uint16_t type = 0; /* for decoding */ /* check for value pointers */ if (apdu_len && data) { len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value_type); if (tag_number != BACNET_APPLICATION_TAG_OBJECT_ID) return -1; len += decode_object_id(&apdu[len], &type, &data->object_instance); data->object_type = (BACNET_OBJECT_TYPE) type; if (decode_is_opening_tag_number(&apdu[len], 0)) { data->access = FILE_STREAM_ACCESS; /* a tag number is not extended so only one octet */ len++; /* fileStartPosition */ tag_len = decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); len += tag_len; if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT) return -1; len += decode_signed(&apdu[len], len_value_type, &data->type.stream.fileStartPosition); /* requestedOctetCount */ tag_len = decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); len += tag_len; if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) return -1; len += decode_unsigned(&apdu[len], len_value_type, &data->type.stream.requestedOctetCount); if (!decode_is_closing_tag_number(&apdu[len], 0)) return -1; /* a tag number is not extended so only one octet */ len++; } else if (decode_is_opening_tag_number(&apdu[len], 1)) { data->access = FILE_RECORD_ACCESS; /* a tag number is not extended so only one octet */ len++; /* fileStartRecord */ tag_len = decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); len += tag_len; if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT) return -1; len += decode_signed(&apdu[len], len_value_type, &data->type.record.fileStartRecord); /* RecordCount */ tag_len = decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); len += tag_len; if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) return -1; len += decode_unsigned(&apdu[len], len_value_type, &data->type.record.RecordCount); if (!decode_is_closing_tag_number(&apdu[len], 1)) return -1; /* a tag number is not extended so only one octet */ len++; } else return -1; } return len; }
/* decode the service request only */ int rp_decode_service_request( uint8_t * apdu, unsigned apdu_len, BACNET_READ_PROPERTY_DATA * rpdata) { unsigned len = 0; uint8_t tag_number = 0; uint32_t len_value_type = 0; uint16_t type = 0; /* for decoding */ uint32_t property = 0; /* for decoding */ uint32_t array_value = 0; /* for decoding */ /* check for value pointers */ if (rpdata != NULL) { /* Must have at least 2 tags, an object id and a property identifier * of at least 1 byte in length to have any chance of parsing */ if (apdu_len < 7) { rpdata->error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER; return BACNET_STATUS_REJECT; } /* Tag 0: Object ID */ if (!decode_is_context_tag(&apdu[len++], 0)) { rpdata->error_code = ERROR_CODE_REJECT_INVALID_TAG; return BACNET_STATUS_REJECT; } len += decode_object_id(&apdu[len], &type, &rpdata->object_instance); rpdata->object_type = (BACNET_OBJECT_TYPE) type; /* Tag 1: Property ID */ len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number != 1) { rpdata->error_code = ERROR_CODE_REJECT_INVALID_TAG; return BACNET_STATUS_REJECT; } len += decode_enumerated(&apdu[len], len_value_type, &property); rpdata->object_property = (BACNET_PROPERTY_ID) property; /* Tag 2: Optional Array Index */ if (len < apdu_len) { len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if ((tag_number == 2) && (len < apdu_len)) { len += decode_unsigned(&apdu[len], len_value_type, &array_value); rpdata->array_index = array_value; } else { rpdata->error_code = ERROR_CODE_REJECT_INVALID_TAG; return BACNET_STATUS_REJECT; } } else rpdata->array_index = BACNET_ARRAY_ALL; } if (len < apdu_len) { /* If something left over now, we have an invalid request */ rpdata->error_code = ERROR_CODE_REJECT_TOO_MANY_ARGUMENTS; return BACNET_STATUS_REJECT; } return (int) len; }
/* FIXME: there could be various error messages returned using unique values less than zero */ int wp_decode_service_request( uint8_t * apdu, unsigned apdu_len, BACNET_WRITE_PROPERTY_DATA * wpdata) { int len = 0; int tag_len = 0; uint8_t tag_number = 0; uint32_t len_value_type = 0; uint16_t type = 0; /* for decoding */ uint32_t property = 0; /* for decoding */ uint32_t unsigned_value = 0; int i = 0; /* loop counter */ /* check for value pointers */ if (apdu_len && wpdata) { /* Tag 0: Object ID */ if (!decode_is_context_tag(&apdu[len++], 0)) return -1; len += decode_object_id(&apdu[len], &type, &wpdata->object_instance); wpdata->object_type = (BACNET_OBJECT_TYPE) type; /* Tag 1: Property ID */ len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number != 1) return -1; len += decode_enumerated(&apdu[len], len_value_type, &property); wpdata->object_property = (BACNET_PROPERTY_ID) property; /* Tag 2: Optional Array Index */ /* note: decode without incrementing len so we can check for opening tag */ tag_len = decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number == 2) { len += tag_len; len += decode_unsigned(&apdu[len], len_value_type, &unsigned_value); wpdata->array_index = unsigned_value; } else wpdata->array_index = BACNET_ARRAY_ALL; /* Tag 3: opening context tag */ if (!decode_is_opening_tag_number(&apdu[len], 3)) return -1; /* determine the length of the data blob */ wpdata->application_data_len = bacapp_data_len(&apdu[len], apdu_len - len, (BACNET_PROPERTY_ID) property); /* a tag number of 3 is not extended so only one octet */ len++; /* copy the data from the APDU */ for (i = 0; i < wpdata->application_data_len; i++) { wpdata->application_data[i] = apdu[len + i]; } /* add on the data length */ len += wpdata->application_data_len; if (!decode_is_closing_tag_number(&apdu[len], 3)) return -2; /* a tag number of 3 is not extended so only one octet */ len++; /* Tag 4: optional Priority - assumed MAX if not explicitly set */ wpdata->priority = BACNET_MAX_PRIORITY; if ((unsigned) len < apdu_len) { tag_len = decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type); if (tag_number == 4) { len += tag_len; len = decode_unsigned(&apdu[len], len_value_type, &unsigned_value); if ((unsigned_value >= BACNET_MIN_PRIORITY) && (unsigned_value <= BACNET_MAX_PRIORITY)) { wpdata->priority = (uint8_t) unsigned_value; } else return -5; } } } return len; }