Exemplo n.º 1
0
void testReject(
    Test * pTest)
{
    uint8_t apdu[480] = { 0 };
    int len = 0;
    int apdu_len = 0;
    uint8_t invoke_id = 0;
    uint8_t reject_reason = 0;
    uint8_t test_invoke_id = 0;
    uint8_t test_reject_reason = 0;

    len = reject_encode_apdu(&apdu[0], invoke_id, reject_reason);
    ct_test(pTest, len != 0);
    apdu_len = len;

    len =
        reject_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
        &test_reject_reason);
    ct_test(pTest, len != -1);
    ct_test(pTest, test_invoke_id == invoke_id);
    ct_test(pTest, test_reject_reason == reject_reason);

    /* change type to get negative response */
    apdu[0] = PDU_TYPE_ABORT;
    len =
        reject_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
        &test_reject_reason);
    ct_test(pTest, len == -1);

    /* test NULL APDU */
    len =
        reject_decode_apdu(NULL, apdu_len, &test_invoke_id,
        &test_reject_reason);
    ct_test(pTest, len == -1);

    /* force a zero length */
    len =
        reject_decode_apdu(&apdu[0], 0, &test_invoke_id, &test_reject_reason);
    ct_test(pTest, len == 0);


    /* check them all...   */
    for (invoke_id = 0; invoke_id < 255; invoke_id++) {
        for (reject_reason = 0; reject_reason < 255; reject_reason++) {
            len = reject_encode_apdu(&apdu[0], invoke_id, reject_reason);
            apdu_len = len;
            ct_test(pTest, len != 0);
            len =
                reject_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
                &test_reject_reason);
            ct_test(pTest, len != -1);
            ct_test(pTest, test_invoke_id == invoke_id);
            ct_test(pTest, test_reject_reason == reject_reason);
        }
    }
}
Exemplo n.º 2
0
/** Check to see if the current Device supports this service.
 * Presently checks for RD and DCC and only allows them if the current
 * device is the gateway device.
 *
 * @param service [in] The service being requested.
 * @param service_argument [in] An optional argument (eg, service type).
 * @param apdu_buff [in,out] The buffer where we will encode a Reject message.
 *                              May be NULL if don't want an encoded response.
 * @param invoke_id [in] The invoke_id of the service request.
 * @return Length of bytes encoded in apdu_buff[] for a Reject message,
 *          just 1 if no apdu_buff was supplied and service is not supported,
 *          else 0 if service is approved for the current device.
 */
int Routed_Device_Service_Approval(
    BACNET_CONFIRMED_SERVICE service,
    int service_argument,
    uint8_t * apdu_buff,
    uint8_t invoke_id)
{
    int len = 0;
    switch (service) {
    case SERVICE_CONFIRMED_REINITIALIZE_DEVICE:
        /* If not the gateway device, we don't support RD */
        if (iCurrent_Device_Idx > 0) {
            if (apdu_buff != NULL)
                len =
                    reject_encode_apdu(apdu_buff, invoke_id,
                                       REJECT_REASON_UNRECOGNIZED_SERVICE);
            else
                len = 1;    /* Non-zero return */
        }
        break;
    case SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL:
        /* If not the gateway device, we don't support DCC */
        if (iCurrent_Device_Idx > 0) {
            if (apdu_buff != NULL)
                len =
                    reject_encode_apdu(apdu_buff, invoke_id,
                                       REJECT_REASON_UNRECOGNIZED_SERVICE);
            else
                len = 1;    /* Non-zero return */
        }
        break;
    default:
        /* Everything else is a pass, at this time. */
        break;
    }
    return len;
}
/** Handler for a ReadPropertyMultiple Service request.
 * @ingroup DSRPM
 * 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 the response would be too large
 * - the result from each included read request, if it succeeds
 * - an Error if processing fails for all, or individual errors if only some fail,
 *   or there isn't enough room in the APDU to fit the data.
 *
 * @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_read_property_multiple(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    int len = 0;
    uint16_t copy_len = 0;
    uint16_t decode_len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    int bytes_sent;
    BACNET_ADDRESS my_address;
    BACNET_RPM_DATA rpmdata;
    int apdu_len = 0;
    int npdu_len = 0;
    int error = 0;

    /* jps_debug - see if we are utilizing all the buffer */
    /* memset(&Handler_Transmit_Buffer[0], 0xff, sizeof(Handler_Transmit_Buffer)); */
    /* encode the NPDU portion of the packet */
    datalink_get_my_address(&my_address);
    npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
    npdu_len =
        npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
                        &npdu_data);
    if (service_data->segmented_message) {
        rpmdata.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
        error = BACNET_STATUS_ABORT;
#if PRINT_ENABLED
        fprintf(stderr, "RPM: Segmented message. Sending Abort!\r\n");
#endif
        goto RPM_FAILURE;
    }
    /* decode apdu request & encode apdu reply
       encode complex ack, invoke id, service choice */
    apdu_len =
        rpm_ack_encode_apdu_init(&Handler_Transmit_Buffer[npdu_len],
                                 service_data->invoke_id);
    for (;;) {
        /* Start by looking for an object ID */
        len =
            rpm_decode_object_id(&service_request[decode_len],
                                 service_len - decode_len, &rpmdata);
        if (len >= 0) {
            /* Got one so skip to next stage */
            decode_len += len;
        } else {
            /* bad encoding - skip to error/reject/abort handling */
#if PRINT_ENABLED
            fprintf(stderr, "RPM: Bad Encoding.\n");
#endif
            error = len;
            goto RPM_FAILURE;
        }

        /* Test for case of indefinite Device object instance */
        if ((rpmdata.object_type == OBJECT_DEVICE) &&
                (rpmdata.object_instance == BACNET_MAX_INSTANCE)) {
            rpmdata.object_instance = Device_Object_Instance_Number();
        }

        /* Stick this object id into the reply - if it will fit */
        len = rpm_ack_encode_apdu_object_begin(&Temp_Buf[0], &rpmdata);
        copy_len =
            memcopy(&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0], apdu_len,
                    len, MAX_APDU);
        if (copy_len == 0) {
#if PRINT_ENABLED
            fprintf(stderr, "RPM: Response too big!\r\n");
#endif
            rpmdata.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
            error = BACNET_STATUS_ABORT;
            goto RPM_FAILURE;
        }

        apdu_len += copy_len;
        /* do each property of this object of the RPM request */
        for (;;) {
            /* Fetch a property */
            len =
                rpm_decode_object_property(&service_request[decode_len],
                                           service_len - decode_len, &rpmdata);
            if (len < 0) {
                /* bad encoding - skip to error/reject/abort handling */
#if PRINT_ENABLED
                fprintf(stderr, "RPM: Bad Encoding.\n");
#endif
                error = len;
                goto RPM_FAILURE;
            }
            decode_len += len;
            /* handle the special properties */
            if ((rpmdata.object_property == PROP_ALL) ||
                    (rpmdata.object_property == PROP_REQUIRED) ||
                    (rpmdata.object_property == PROP_OPTIONAL)) {
                struct special_property_list_t property_list;
                unsigned property_count = 0;
                unsigned index = 0;
                BACNET_PROPERTY_ID special_object_property;

                if (rpmdata.array_index != BACNET_ARRAY_ALL) {
                    /*  No array index options for this special property.
                       Encode error for this object property response */
                    len =
                        rpm_ack_encode_apdu_object_property(&Temp_Buf[0],
                                                            rpmdata.object_property, rpmdata.array_index);
                    copy_len =
                        memcopy(&Handler_Transmit_Buffer[npdu_len],
                                &Temp_Buf[0], apdu_len, len, MAX_APDU);
                    if (copy_len == 0) {
#if PRINT_ENABLED
                        fprintf(stderr,
                                "RPM: Too full to encode property!\r\n");
#endif
                        rpmdata.error_code =
                            ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
                        error = BACNET_STATUS_ABORT;
                        goto RPM_FAILURE;
                    }
                    apdu_len += len;
                    len =
                        rpm_ack_encode_apdu_object_property_error(&Temp_Buf[0],
                                ERROR_CLASS_PROPERTY,
                                ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY);
                    copy_len =
                        memcopy(&Handler_Transmit_Buffer[npdu_len],
                                &Temp_Buf[0], apdu_len, len, MAX_APDU);
                    if (copy_len == 0) {
#if PRINT_ENABLED
                        fprintf(stderr, "RPM: Too full to encode error!\r\n");
#endif
                        rpmdata.error_code =
                            ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
                        error = BACNET_STATUS_ABORT;
                        goto RPM_FAILURE;
                    }
                    apdu_len += len;
                } else {
                    special_object_property = rpmdata.object_property;
                    Device_Objects_Property_List(rpmdata.object_type,
                                                 &property_list);
                    property_count =
                        RPM_Object_Property_Count(&property_list,
                                                  special_object_property);
                    if (property_count == 0) {
                        /* handle the error code - but use the special property */
                        len =
                            RPM_Encode_Property(&Handler_Transmit_Buffer
                                                [npdu_len], (uint16_t) apdu_len, MAX_APDU,
                                                &rpmdata);
                        if (len > 0) {
                            apdu_len += len;
                        } else {
#if PRINT_ENABLED
                            fprintf(stderr,
                                    "RPM: Too full for special property!\r\n");
#endif
                            error = len;
                            goto RPM_FAILURE;
                        }
                    } else {
                        for (index = 0; index < property_count; index++) {
                            rpmdata.object_property =
                                RPM_Object_Property(&property_list,
                                                    special_object_property, index);
                            len =
                                RPM_Encode_Property(&Handler_Transmit_Buffer
                                                    [npdu_len], (uint16_t) apdu_len, MAX_APDU,
                                                    &rpmdata);
                            if (len > 0) {
                                apdu_len += len;
                            } else {
#if PRINT_ENABLED
                                fprintf(stderr,
                                        "RPM: Too full for property!\r\n");
#endif
                                error = len;
                                goto RPM_FAILURE;
                            }
                        }
                    }
                }
            } else {
                /* handle an individual property */
                len =
                    RPM_Encode_Property(&Handler_Transmit_Buffer[npdu_len],
                                        (uint16_t) apdu_len, MAX_APDU, &rpmdata);
                if (len > 0) {
                    apdu_len += len;
                } else {
#if PRINT_ENABLED
                    fprintf(stderr,
                            "RPM: Too full for individual property!\r\n");
#endif
                    error = len;
                    goto RPM_FAILURE;
                }
            }
            if (decode_is_closing_tag_number(&service_request[decode_len], 1)) {
                /* Reached end of property list so cap the result list */
                decode_len++;
                len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
                copy_len =
                    memcopy(&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
                            apdu_len, len, MAX_APDU);
                if (copy_len == 0) {
#if PRINT_ENABLED
                    fprintf(stderr, "RPM: Too full to encode object end!\r\n");
#endif
                    rpmdata.error_code =
                        ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
                    error = BACNET_STATUS_ABORT;
                    goto RPM_FAILURE;
                } else {
                    apdu_len += copy_len;
                }
                break;  /* finished with this property list */
            }
        }
        if (decode_len >= service_len) {
            /* Reached the end so finish up */
            break;
        }
    }

    if (apdu_len > service_data->max_resp) {
        /* too big for the sender - send an abort */
        rpmdata.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
        error = BACNET_STATUS_ABORT;
#if PRINT_ENABLED
        fprintf(stderr, "RPM: Message too large.  Sending Abort!\n");
#endif
        goto RPM_FAILURE;
    }

RPM_FAILURE:
    if (error) {
        if (error == BACNET_STATUS_ABORT) {
            apdu_len =
                abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                                  service_data->invoke_id,
                                  abort_convert_error_code(rpmdata.error_code), true);
#if PRINT_ENABLED
            fprintf(stderr, "RPM: Sending Abort!\n");
#endif
        } else if (error == BACNET_STATUS_ERROR) {
            apdu_len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                                     service_data->invoke_id, SERVICE_CONFIRMED_READ_PROP_MULTIPLE,
                                     rpmdata.error_class, rpmdata.error_code);
#if PRINT_ENABLED
            fprintf(stderr, "RPM: Sending Error!\n");
#endif
        } else if (error == BACNET_STATUS_REJECT) {
            apdu_len =
                reject_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                                   service_data->invoke_id,
                                   reject_convert_error_code(rpmdata.error_code));
#if PRINT_ENABLED
            fprintf(stderr, "RPM: Sending Reject!\n");
#endif
        }
    }

    pdu_len = apdu_len + npdu_len;
    bytes_sent =
        datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
                          pdu_len);
#if PRINT_ENABLED
    if (bytes_sent <= 0) {
        fprintf(stderr, "RPM: Failed to send PDU (%s)!\n", strerror(errno));
    }
#else
    bytes_sent = bytes_sent;
#endif
}
Exemplo n.º 4
0
/** Handler for a Reinitialize Device (RD) request.
 * @ingroup DMRD
 * 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
 * - an Error if
 *   - the RD password is incorrect
 *   - the Reinitialize Device operation fails
 * - a Reject if the request state is invalid
 * - else tries to send a simple ACK for the RD on success.
 *
 * @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_reinitialize_device(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_REINITIALIZE_DEVICE_DATA rd_data;
    int len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    BACNET_ADDRESS my_address;

    /* encode the NPDU portion of the 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, "ReinitializeDevice!\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,
            "ReinitializeDevice: Sending Abort - segmented message.\n");
#endif
        goto RD_ABORT;
    }
    /* decode the service request only */
    len =
        rd_decode_service_request(service_request, service_len, &rd_data.state,
        &rd_data.password);
#if PRINT_ENABLED
    if (len > 0) {
        fprintf(stderr, "ReinitializeDevice: state=%u password=%s\n",
            (unsigned) rd_data.state,
            characterstring_value(&rd_data.password));
    } else {
        fprintf(stderr, "ReinitializeDevice: Unable to decode request!\n");
    }
#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,
            "ReinitializeDevice: Sending Abort - could not decode.\n");
#endif
        goto RD_ABORT;
    }
    /* check the data from the request */
    if (rd_data.state >= MAX_BACNET_REINITIALIZED_STATE) {
        len =
            reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION);
#if PRINT_ENABLED
        fprintf(stderr,
            "ReinitializeDevice: 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_REINITIALIZE_DEVICE, (int) rd_data.state,
            &Handler_Transmit_Buffer[pdu_len], service_data->invoke_id);
        if (len > 0)
            goto RD_ABORT;
#endif

        if (Device_Reinitialize(&rd_data)) {
            len =
                encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id,
                SERVICE_CONFIRMED_REINITIALIZE_DEVICE);
#if PRINT_ENABLED
            fprintf(stderr, "ReinitializeDevice: Sending Simple Ack!\n");
#endif
        } else {
            len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
                rd_data.error_class, rd_data.error_code);
#if PRINT_ENABLED
            fprintf(stderr, "ReinitializeDevice: Sending Error.\n");
#endif
        }
    }
  RD_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, "ReinitializeDevice: Failed to send PDU (%s)!\n",
            strerror(errno));
#endif
    }

    return;
}
Exemplo n.º 5
0
/** 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;
}
Exemplo n.º 6
0
/** Handler for a ReadProperty Service request.
 * @ingroup DSRP
 * 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 the response would be too large
 * - the result from Device_Read_Property(), if it succeeds
 * - an Error if Device_Read_Property() fails
 *   or there isn't enough room in the APDU to fit the data.
 *
 * @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_read_property(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_READ_PROPERTY_DATA rpdata;
    int len = 0;
    int pdu_len = 0;
    int apdu_len = -1;
    int npdu_len = -1;
    BACNET_NPDU_DATA npdu_data;
    bool error = true;  /* assume that there is an error */
    int bytes_sent = 0;
    BACNET_ADDRESS my_address;

    /* configure default error code as an abort since it is common */
    rpdata.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
    /* encode the NPDU portion of the packet */
    datalink_get_my_address(&my_address);
    npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
    npdu_len =
        npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
        &npdu_data);
    if (service_data->segmented_message) {
        /* we don't support segmentation - send an abort */
        len = BACNET_STATUS_ABORT;
#if PRINT_ENABLED
        fprintf(stderr, "RP: Segmented message.  Sending Abort!\n");
#endif
        goto RP_FAILURE;
    }
    len = rp_decode_service_request(service_request, service_len, &rpdata);
#if PRINT_ENABLED
    if (len <= 0) {
        fprintf(stderr, "RP: Unable to decode Request!\n");
    }
#endif
    if (len < 0) {
        /* bad decoding - skip to error/reject/abort handling */
        error = true;
#if PRINT_ENABLED
        fprintf(stderr, "RP: Bad Encoding.\n");
#endif
        goto RP_FAILURE;
    }
    /* Test for case of indefinite Device object instance */
    if ((rpdata.object_type == OBJECT_DEVICE) &&
        (rpdata.object_instance == BACNET_MAX_INSTANCE)) {
        rpdata.object_instance = Device_Object_Instance_Number();
    }

    apdu_len =
        rp_ack_encode_apdu_init(&Handler_Transmit_Buffer[npdu_len],
        service_data->invoke_id, &rpdata);
    /* configure our storage */
    rpdata.application_data = &Handler_Transmit_Buffer[npdu_len + apdu_len];
    rpdata.application_data_len =
        sizeof(Handler_Transmit_Buffer) - (npdu_len + apdu_len);
    len = Device_Read_Property(&rpdata);
    if (len >= 0) {
        apdu_len += len;
        len =
            rp_ack_encode_apdu_object_property_end(&Handler_Transmit_Buffer
            [npdu_len + apdu_len]);
        apdu_len += len;
        if (apdu_len > service_data->max_resp) {
            /* too big for the sender - send an abort
             * Setting of error code needed here as read property processing may
             * have overriden the default set at start */
            rpdata.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
            len = BACNET_STATUS_ABORT;
#if PRINT_ENABLED
            fprintf(stderr, "RP: Message too large.\n");
#endif
        } else {
#if PRINT_ENABLED
            fprintf(stderr, "RP: Sending Ack!\n");
#endif
            error = false;
        }
    } else {
#if PRINT_ENABLED
        fprintf(stderr, "RP: Device_Read_Property: ");
        if (len == BACNET_STATUS_ABORT) {
            fprintf(stderr, "Abort!\n");
        } else if (len == BACNET_STATUS_ERROR) {
            fprintf(stderr, "Error!\n");
        } else if (len == BACNET_STATUS_REJECT) {
            fprintf(stderr, "Reject!\n");
        } else {
            fprintf(stderr, "Unknown Len=%d\n", len);
        }
#endif
    }

  RP_FAILURE:
    if (error) {
        if (len == BACNET_STATUS_ABORT) {
            apdu_len =
                abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_data->invoke_id,
                abort_convert_error_code(rpdata.error_code), true);
#if PRINT_ENABLED
            fprintf(stderr, "RP: Sending Abort!\n");
#endif
        } else if (len == BACNET_STATUS_ERROR) {
            apdu_len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
                rpdata.error_class, rpdata.error_code);
#if PRINT_ENABLED
            fprintf(stderr, "RP: Sending Error!\n");
#endif
        } else if (len == BACNET_STATUS_REJECT) {
            apdu_len =
                reject_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_data->invoke_id,
                reject_convert_error_code(rpdata.error_code));
#if PRINT_ENABLED
            fprintf(stderr, "RP: Sending Reject!\n");
#endif
        }
    }

    pdu_len = npdu_len + apdu_len;
    bytes_sent =
        datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
        pdu_len);
#if PRINT_ENABLED
    if (bytes_sent <= 0) {
        fprintf(stderr, "Failed to send PDU (%s)!\n", strerror(errno));
    }
#else
    bytes_sent = bytes_sent;
#endif

    return;
}
Exemplo n.º 7
0
/** Handler for a COV Subscribe Service request.
 * @ingroup DSCOV
 * 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
 * - an ACK, if cov_subscribe() succeeds
 * - an Error if cov_subscribe() fails
 *
 * @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_cov_subscribe(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_SUBSCRIBE_COV_DATA cov_data;
    int len = 0;
    int pdu_len = 0;
    int npdu_len = 0;
    int apdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    bool success = false;
    int bytes_sent = 0;
    BACNET_ADDRESS my_address;
    bool error = false;

    /* initialize a common abort code */
    cov_data.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
    /* encode the NPDU portion of the packet */
    datalink_get_my_address(&my_address);
    npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
    npdu_len =
        npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
        &npdu_data);
    if (service_data->segmented_message) {
        /* we don't support segmentation - send an abort */
        len = BACNET_STATUS_ABORT;
#if PRINT_ENABLED
        fprintf(stderr, "SubscribeCOV: Segmented message.  Sending Abort!\n");
#endif
        error = true;
        goto COV_ABORT;
    }
    len =
        cov_subscribe_decode_service_request(service_request, service_len,
        &cov_data);
#if PRINT_ENABLED
    if (len <= 0)
        fprintf(stderr, "SubscribeCOV: Unable to decode Request!\n");
#endif
    if (len < 0) {
        error = true;
        goto COV_ABORT;
    }
    cov_data.error_class = ERROR_CLASS_OBJECT;
    cov_data.error_code = ERROR_CODE_UNKNOWN_OBJECT;
    success =
        cov_subscribe(src, &cov_data, &cov_data.error_class,
        &cov_data.error_code);
    if (success) {
        apdu_len =
            encode_simple_ack(&Handler_Transmit_Buffer[npdu_len],
            service_data->invoke_id, SERVICE_CONFIRMED_SUBSCRIBE_COV);
#if PRINT_ENABLED
        fprintf(stderr, "SubscribeCOV: Sending Simple Ack!\n");
#endif
    } else {
        len = BACNET_STATUS_ERROR;
        error = true;
#if PRINT_ENABLED
        fprintf(stderr, "SubscribeCOV: Sending Error!\n");
#endif
    }
  COV_ABORT:
    if (error) {
        if (len == BACNET_STATUS_ABORT) {
            apdu_len =
                abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_data->invoke_id,
                abort_convert_error_code(cov_data.error_code), true);
#if PRINT_ENABLED
            fprintf(stderr, "SubscribeCOV: Sending Abort!\n");
#endif
        } else if (len == BACNET_STATUS_ERROR) {
            apdu_len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_data->invoke_id, SERVICE_CONFIRMED_SUBSCRIBE_COV,
                cov_data.error_class, cov_data.error_code);
#if PRINT_ENABLED
            fprintf(stderr, "SubscribeCOV: Sending Error!\n");
#endif
        } else if (len == BACNET_STATUS_REJECT) {
            apdu_len =
                reject_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_data->invoke_id,
                reject_convert_error_code(cov_data.error_code));
#if PRINT_ENABLED
            fprintf(stderr, "SubscribeCOV: Sending Reject!\n");
#endif
        }
    }
    pdu_len = npdu_len + apdu_len;
    bytes_sent =
        datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
        pdu_len);
#if PRINT_ENABLED
    if (bytes_sent <= 0)
        fprintf(stderr, "SubscribeCOV: Failed to send PDU (%s)!\n",
            strerror(errno));
#else
    bytes_sent = bytes_sent;
#endif

    return;
}
Exemplo n.º 8
0
void handler_read_property_ack2(
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_ACK_DATA * service_ack_data,
    uint8_t * apdu,
    uint16_t apdu_len)
{
    BACNET_READ_PROPERTY_DATA rpdata;
    int len = 0;
    int pdu_len = 0;
    int npdu_len = -1;
    BACNET_NPDU_DATA npdu_data;
    bool error = true;  /* assume that there is an error */
    int bytes_sent = 0;
    BACNET_ADDRESS my_address;

    fprintf(stderr, "Entering handler_RP2 in h_rp.c.\n");
    /* configure default error code as an abort since it is common */
    rpdata.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
    /* encode the NPDU portion of the packet */
    /* returns my IP addr (4 bytes) and port num (2bytes)*/
    datalink_get_my_address(&my_address);
    //set up NPCI header field npdu_data
    npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
    npdu_len =
        npdu_encode_pdu(&Handler_Transmit_Buffer_ACK[0], src, &my_address,//src!!
        &npdu_data);//set up handler transmit buffer by injecting npci/src/dst addr info
    if (service_ack_data->segmented_message) {
        /* we don't support segmentation - send an abort */
        len = BACNET_STATUS_ABORT;
#if PRINT_ENABLED
        fprintf(stderr, "RP: Segmented message.  Sending Abort!\n");
#endif
        goto RP_FAILURE;
    }

    int i;
    for (i = 0; i < apdu_len; ++i){
        Handler_Transmit_Buffer_ACK[npdu_len + i] = apdu[i];
    }
    fprintf(stderr, "Finish copying apdu to ack buffer in h_rp.c.\n");

  RP_FAILURE:
    if (error) {
        if (len == BACNET_STATUS_ABORT) {
            apdu_len =
                abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_ack_data->invoke_id,
                abort_convert_error_code(rpdata.error_code), true);
#if PRINT_ENABLED
            fprintf(stderr, "RP: Sending Abort!\n");
#endif
        } else if (len == BACNET_STATUS_ERROR) {
            apdu_len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_ack_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
                rpdata.error_class, rpdata.error_code);
#if PRINT_ENABLED
            fprintf(stderr, "RP: Sending Error!\n");
#endif
        } else if (len == BACNET_STATUS_REJECT) {
            apdu_len =
                reject_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
                service_ack_data->invoke_id,
                reject_convert_error_code(rpdata.error_code));
#if PRINT_ENABLED
            fprintf(stderr, "RP: Sending Reject!\n");
#endif
        }
    }


    pdu_len = npdu_len + apdu_len;
    bytes_sent =
        datalink_send_pdu(rp_serv_addr, &npdu_data, &Handler_Transmit_Buffer_ACK[0],
        pdu_len);
#if PRINT_ENABLED
    if (bytes_sent <= 0) {
        fprintf(stderr, "Failed to send PDU (%s)!\n", strerror(errno));
    }else{
        fprintf(stderr, "sent pdu back to server in h_rp.c.\n");
    }
#else
    bytes_sent = bytes_sent;
#endif

    return;
}
Exemplo n.º 9
0
void handler_reinitialize_device(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_REINITIALIZED_STATE state;
    BACNET_CHARACTER_STRING their_password;
    int len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    int bytes_sent = 0;
    BACNET_ADDRESS my_address;

    /* encode the NPDU portion of the 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 (service_data->segmented_message) {
        len =
            abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
            true);
        goto RD_ABORT;
    }
    /* decode the service request only */
    len =
        rd_decode_service_request(service_request, service_len, &state,
        &their_password);
    /* 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);
        goto RD_ABORT;
    }
    /* check the data from the request */
    if (state >= MAX_BACNET_REINITIALIZED_STATE) {
        len =
            reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION);
    } else {
        characterstring_init_ansi(&My_Password, Password);
        if (characterstring_same(&their_password, &My_Password)) {
            len =
                encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id,
                SERVICE_CONFIRMED_REINITIALIZE_DEVICE);
            /* FIXME: now you can reboot, restart, quit, or something clever */
            /* Note: you can use a mix of state and password to do specific stuff */
            /* Note: if you don't do something clever like actually restart,
               you probably should clear any DCC status and timeouts */
            /* Note: you probably need to send the reply BEFORE restarting */
        } else {
            len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
                ERROR_CLASS_SERVICES, ERROR_CODE_PASSWORD_FAILURE);
        }
    }
  RD_ABORT:
    pdu_len += len;
    bytes_sent =
        datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
        pdu_len);

    return;
}