Exemple #1
0
void apdu_handler(
    BACNET_ADDRESS * src,
    uint8_t * apdu,     /* APDU data */
    uint16_t apdu_len)
{
    BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
    uint8_t service_choice = 0;
    uint8_t *service_request = NULL;
    uint16_t service_request_len = 0;
    uint16_t len = 0;   /* counts where we are in PDU */

    if (apdu) {
        /* PDU Type */
        switch (apdu[0] & 0xF0) {
        case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
            len = apdu_decode_confirmed_service_request(&apdu[0],   /* APDU data */
                    apdu_len, &service_data, &service_choice, &service_request,
                    &service_request_len);
            if (service_choice == SERVICE_CONFIRMED_READ_PROPERTY) {
                handler_read_property(service_request, service_request_len,
                                      src, &service_data);
            }
#ifdef WRITE_PROPERTY
            else if (service_choice == SERVICE_CONFIRMED_WRITE_PROPERTY) {
                handler_write_property(service_request,
                                       service_request_len, src, &service_data);
            }
#endif
            else {
                handler_unrecognized_service(service_request,
                                             service_request_len, src, &service_data);
            }
            break;
        case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
            service_choice = apdu[1];
            service_request = &apdu[2];
            service_request_len = apdu_len - 2;
            if (service_choice == SERVICE_UNCONFIRMED_WHO_IS) {
                handler_who_is(service_request, service_request_len, src);
            }
            break;
        case PDU_TYPE_SIMPLE_ACK:
        case PDU_TYPE_COMPLEX_ACK:
        case PDU_TYPE_SEGMENT_ACK:
        case PDU_TYPE_ERROR:
        case PDU_TYPE_REJECT:
        case PDU_TYPE_ABORT:
        default:
            break;
        }
    }
    return;
}
Exemple #2
0
void apdu_handler(
    BACNET_ADDRESS * src,
    uint8_t * apdu,     /* APDU data */
    uint16_t apdu_len)
{
    BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
    uint8_t service_choice = 0;
    uint8_t *service_request = NULL;
    uint16_t service_request_len = 0;
    uint16_t len = 0;   /* counts where we are in PDU */

    if (apdu) {
        /* PDU Type */
        switch (apdu[0] & 0xF0) {
            case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
                len = apdu_decode_confirmed_service_request(&apdu[0],   /* APDU data */
                    apdu_len, &service_data, &service_choice, &service_request,
                    &service_request_len);
                if (apdu_confirmed_dcc_disabled(service_choice)) {
                    /* When network communications are completely disabled,
                       only DeviceCommunicationControl and ReinitializeDevice APDUs
                       shall be processed and no messages shall be initiated. */
                    break;
                }
                if (service_choice == SERVICE_CONFIRMED_READ_PROPERTY) {
                    handler_read_property(service_request, service_request_len,
                        src, &service_data);
                } else if (service_choice == SERVICE_CONFIRMED_WRITE_PROPERTY) {
                    handler_write_property(service_request,
                        service_request_len, src, &service_data);
                } else if (service_choice ==
                    SERVICE_CONFIRMED_REINITIALIZE_DEVICE) {
                    handler_reinitialize_device(service_request,
                        service_request_len, src, &service_data);
                } else if (service_choice ==
                    SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL) {
                    handler_device_communication_control(service_request,
                        service_request_len, src, &service_data);
                } else {
                    handler_unrecognized_service(service_request,
                        service_request_len, src, &service_data);
                }
                break;
            case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
                service_choice = apdu[1];
                service_request = &apdu[2];
                service_request_len = apdu_len - 2;
                if (apdu_unconfirmed_dcc_disabled(service_choice)) {
                    /* When network communications are disabled,
                       only DeviceCommunicationControl and ReinitializeDevice APDUs
                       shall be processed and no messages shall be initiated.
                       If communications have been initiation disabled, then
                       WhoIs may be processed. */
                    break;
                }
                if (service_choice == SERVICE_UNCONFIRMED_WHO_IS) {
                    handler_who_is(service_request, service_request_len, src);
                }
                break;
            case PDU_TYPE_SIMPLE_ACK:
            case PDU_TYPE_COMPLEX_ACK:
            case PDU_TYPE_SEGMENT_ACK:
            case PDU_TYPE_ERROR:
            case PDU_TYPE_REJECT:
            case PDU_TYPE_ABORT:
            default:
                break;
        }
    }
    return;
}
Exemple #3
0
/** Process the APDU header and invoke the appropriate service handler
 * to manage the received request.
 * Almost all requests and ACKs invoke this function.
 * @ingroup MISCHNDLR
 *
 * @param src [in] The BACNET_ADDRESS of the message's source.
 * @param apdu [in] The apdu portion of the request, to be processed.
 * @param apdu_len [in] The total (remaining) length of the apdu.
 */
void apdu_handler(
    BACNET_ADDRESS * src,
    uint8_t * apdu,     /* APDU data */
    uint16_t apdu_len)
{
    BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
    BACNET_CONFIRMED_SERVICE_ACK_DATA service_ack_data = { 0 };
    //uint8_t invoke_id = 0;
    uint8_t service_choice = 0;
    uint8_t *service_request = NULL;
    uint16_t service_request_len = 0;
    int len = 0;        /* counts where we are in PDU */
    uint8_t tag_number = 0;
    uint32_t len_value = 0;
    uint32_t error_code = 0;
    uint32_t error_class = 0;
   // uint8_t reason = 0;
   // bool server = false;
    if (apdu) {	 
        /* PDU Type */
        switch (apdu[0] & 0xF0) {
            case PDU_TYPE_CONFIRMED_SERVICE_REQUEST: 	
                len =
                    (int) apdu_decode_confirmed_service_request(&apdu[0],
                    apdu_len, &service_data, &service_choice, &service_request,
                    &service_request_len);
				
				#if 0
                if (apdu_confirmed_dcc_disabled(service_choice)) {     tbd: chelsea
                    /* When network communications are completely disabled,
                       only DeviceCommunicationControl and ReinitializeDevice APDUs
                       shall be processed and no messages shall be initiated. */
                    break;
                }
                if ((service_choice < MAX_BACNET_CONFIRMED_SERVICE) &&
                    (Confirmed_Function[service_choice]))
                    Confirmed_Function[service_choice] (service_request,
                        service_request_len/*, src, &service_data*/);
                else if (Unrecognized_Service_Handler)
                    Unrecognized_Service_Handler(service_request,
                        service_request_len/*, src, &service_data*/);
				#endif

//				#if READ_WRITE_PROPERTY
				#if 1
				if (service_choice == SERVICE_CONFIRMED_READ_PROPERTY) {
                handler_read_property(service_request,
                    service_request_len, src, &service_data);
	            } else if (service_choice == SERVICE_CONFIRMED_WRITE_PROPERTY) {
	                handler_write_property(service_request,
	                 service_request_len, src, &service_data);
	            } else 
				#endif

				if (service_choice == SERVICE_CONFIRMED_PRIVATE_TRANSFER) 
				{ 	 
	             handler_private_transfer(apdu,apdu_len,src);	 // add private transfer by chelsea
				}
				else
				{ 		
	               handler_unrecognized_service(service_request,
	                   service_request_len, src, &service_data);
	            } 								  
                break;
            case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
			{	
				//U8_T i;
				
                service_choice = apdu[1];
                service_request = &apdu[2];
                service_request_len = apdu_len - 2;
				#if 0
                if (apdu_unconfirmed_dcc_disabled(service_choice)) {
                    /* When network communications are disabled,
                       only DeviceCommunicationControl and ReinitializeDevice APDUs
                       shall be processed and no messages shall be initiated.
                       If communications have been initiation disabled, then
                       WhoIs may be processed. */
                    break;
                }
				
                if (service_choice < MAX_BACNET_UNCONFIRMED_SERVICE) {
                    if (Unconfirmed_Function[service_choice])
                        Unconfirmed_Function[service_choice] (
						service_request,
                            service_request_len/*, src*/);		// tbd: chelsea
                }
				#endif				
				if (service_choice == SERVICE_UNCONFIRMED_WHO_IS) 
				{	
					if(	modbus.protocal == BAC_MSTP)
					{	 
	                	handler_who_is(service_request,
	                     service_request_len, src);
					}
					else if((modbus.protocal == BAC_IP) || (modbus.protocal == BAC_GSM))
					{  	
						Send_I_Am(&Handler_Transmit_Buffer[0]);
					}
            	}
				else if (service_choice == SERVICE_UNCONFIRMED_PRIVATE_TRANSFER) 
				{ // add unconfirmedPrivateTransfer handler, for TEMCO private
					handler_private_transfer(apdu,apdu_len,src);
				}
					
			 }
                break;
            case PDU_TYPE_SIMPLE_ACK: 
//                invoke_id = apdu[1];
                service_choice = apdu[2];
                switch (service_choice) {
                    case SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM:
                    case SERVICE_CONFIRMED_COV_NOTIFICATION:
                    case SERVICE_CONFIRMED_EVENT_NOTIFICATION:
                    case SERVICE_CONFIRMED_SUBSCRIBE_COV:
                    case SERVICE_CONFIRMED_SUBSCRIBE_COV_PROPERTY:
                    case SERVICE_CONFIRMED_LIFE_SAFETY_OPERATION:
                        /* Object Access Services */
                    case SERVICE_CONFIRMED_ADD_LIST_ELEMENT:
                    case SERVICE_CONFIRMED_REMOVE_LIST_ELEMENT:
                    case SERVICE_CONFIRMED_DELETE_OBJECT:
                    case SERVICE_CONFIRMED_WRITE_PROPERTY:
                    case SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE:
                        /* Remote Device Management Services */
                    case SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL:
                    case SERVICE_CONFIRMED_REINITIALIZE_DEVICE:
                    case SERVICE_CONFIRMED_TEXT_MESSAGE:
                        /* Virtual Terminal Services */
                    case SERVICE_CONFIRMED_VT_CLOSE:
                        /* Security Services */
                    case SERVICE_CONFIRMED_REQUEST_KEY:
                        if (Confirmed_ACK_Function[service_choice] != NULL) {
							// tbd: chelsea
//                            ((confirmed_simple_ack_function)
//                                Confirmed_ACK_Function[service_choice]) (src,
//                                invoke_id);
                        }
                    //    tsm_free_invoke_id(invoke_id);
                        break;
                    default:
                        break;
                }
                break;
            case PDU_TYPE_COMPLEX_ACK:
                service_ack_data.segmented_message =
                    (apdu[0] & BIT3) ? true : false;
                service_ack_data.more_follows =
                    (apdu[0] & BIT2) ? true : false;
//                invoke_id = service_ack_data.invoke_id = apdu[1];
                len = 2;
                if (service_ack_data.segmented_message) {
                    service_ack_data.sequence_number = apdu[len++];
                    service_ack_data.proposed_window_number = apdu[len++];
                }
                service_choice = apdu[len++];
                service_request = &apdu[len];
                service_request_len = apdu_len - (uint16_t) len;   
                switch (service_choice) {
                    case SERVICE_CONFIRMED_GET_ALARM_SUMMARY:
                    case SERVICE_CONFIRMED_GET_ENROLLMENT_SUMMARY:
                    case SERVICE_CONFIRMED_GET_EVENT_INFORMATION:
                        /* File Access Services */
                    case SERVICE_CONFIRMED_ATOMIC_READ_FILE:
                    case SERVICE_CONFIRMED_ATOMIC_WRITE_FILE:
                        /* Object Access Services */
                    case SERVICE_CONFIRMED_CREATE_OBJECT:
                    case SERVICE_CONFIRMED_READ_PROPERTY:
                    case SERVICE_CONFIRMED_READ_PROP_CONDITIONAL:
                    case SERVICE_CONFIRMED_READ_PROP_MULTIPLE:
                    case SERVICE_CONFIRMED_READ_RANGE:
                    case SERVICE_CONFIRMED_PRIVATE_TRANSFER:
                        /* Virtual Terminal Services */
                    case SERVICE_CONFIRMED_VT_OPEN:
                    case SERVICE_CONFIRMED_VT_DATA:
                        /* Security Services */
                    case SERVICE_CONFIRMED_AUTHENTICATE:
                        if (Confirmed_ACK_Function[service_choice] != NULL) { 						
//                            (Confirmed_ACK_Function[service_choice])
//                                (service_request, service_request_len/*, src,
//                                &service_ack_data*/);		// tbd: chelsea
                        }
                    //    tsm_free_invoke_id(invoke_id);
                        break;
                    default:
                        break;
                }
                break;
            case PDU_TYPE_SEGMENT_ACK:	 
                /* FIXME: what about a denial of service attack here?
                   we could check src to see if that matched the tsm */
             //   tsm_free_invoke_id(invoke_id);
                break;
            case PDU_TYPE_ERROR:	
//                invoke_id = apdu[1];
                service_choice = apdu[2];
                len = 3;

                /* FIXME: Currently special case for C_P_T but there are others which may
                   need consideration such as ChangeList-Error, CreateObject-Error,
                   WritePropertyMultiple-Error and VTClose_Error but they may be left as
                   is for now until support for these services is added */

                if (service_choice == SERVICE_CONFIRMED_PRIVATE_TRANSFER) {     /* skip over opening tag 0 */
                    if (decode_is_opening_tag_number(&apdu[len], 0)) {
                        len++;  /* a tag number of 0 is not extended so only one octet */
                    }
                }
                len +=
                    decode_tag_number_and_value(&apdu[len], &tag_number,
                    &len_value);
                /* FIXME: we could validate that the tag is enumerated... */
                len += decode_enumerated(&apdu[len], len_value, &error_class);
                len +=
                    decode_tag_number_and_value(&apdu[len], &tag_number,
                    &len_value);
                /* FIXME: we could validate that the tag is enumerated... */
                len += decode_enumerated(&apdu[len], len_value, &error_code);

                if (service_choice == SERVICE_CONFIRMED_PRIVATE_TRANSFER) {     /* skip over closing tag 0 */
                    if (decode_is_closing_tag_number(&apdu[len], 0)) {
                        len++;  /* a tag number of 0 is not extended so only one octet */
                    }
                }
                if (service_choice < MAX_BACNET_CONFIRMED_SERVICE) {
//                    if (Error_Function[service_choice])
//                        Error_Function[service_choice] (src, invoke_id/*,
//                            (BACNET_ERROR_CLASS) error_class,
//                            (BACNET_ERROR_CODE) error_code*/);	  // tbd: chelsea
                }
              //  tsm_free_invoke_id(invoke_id);
                break;
            case PDU_TYPE_REJECT:	  
//                invoke_id = apdu[1];
//                reason = apdu[2];
              //  if (Reject_Function)
              //      Reject_Function(src, invoke_id, reason);
              //  tsm_free_invoke_id(invoke_id);
                break;
            case PDU_TYPE_ABORT:	
//                server = apdu[0] & 0x01;
//                invoke_id = apdu[1];
//                reason = apdu[2];
             //   if (Abort_Function)
             //       Abort_Function(src, invoke_id, reason, server);
            //    tsm_free_invoke_id(invoke_id);
                break;
            default:   
                break;
        }

		memset(Handler_Transmit_Buffer,0,MAX_PDU);
		//printf("apdu_done\r\n");
    }

    return;
}