Beispiel #1
0
    def indication(self, apdu, address, device):
        """logging the received PDU type and Service request"""
        request = None
        apdu_type = apdu_types.get(apdu.apduType)
        invoke_key = apdu.apduInvokeID
        logger.info('Bacnet PDU received from %s:%d. (%s)', address[0],
                    address[1], apdu_type.__name__)
        if apdu_type.pduType == 0x0:
            # Confirmed request handling
            apdu_service = confirmed_request_types.get(apdu.apduService)
            logger.info('Bacnet indication from %s:%d. (%s)', address[0],
                        address[1], apdu_service.__name__)
            try:
                request = apdu_service()
                request.decode(apdu)
            except (AttributeError, RuntimeError,
                    InvalidParameterDatatype) as e:
                logger.warning(
                    'Bacnet indication: Invalid service. Error: %s' % e)
                return
            except bacpypes.errors.DecodingError:
                pass

            for key, value in list(
                    ConfirmedServiceChoice.enumerations.items()):
                if apdu_service.serviceChoice == value:
                    try:
                        getattr(self, key)(request, address, invoke_key,
                                           device)
                        break
                    except AttributeError:
                        logger.error('Not implemented Bacnet command')
                        self._response = None
                        return
            else:
                logger.info(
                    'Bacnet indication: Invalid confirmed service choice (%s)',
                    apdu_service.__name__)
                self._response = None
                return

        # Unconfirmed request handling
        elif apdu_type.pduType == 0x1:
            apdu_service = unconfirmed_request_types.get(apdu.apduService)
            logger.info('Bacnet indication from %s:%d. (%s)', address[0],
                        address[1], apdu_service.__name__)
            try:
                request = apdu_service()
                request.decode(apdu)
            except (AttributeError, RuntimeError):
                logger.exception('Bacnet indication: Invalid service.')
                self._response = None
                return
            except bacpypes.errors.DecodingError:
                pass

            for key, value in list(
                    UnconfirmedServiceChoice.enumerations.items()):
                if apdu_service.serviceChoice == value:
                    try:
                        getattr(self, key)(request, address, invoke_key,
                                           device)
                        break
                    except AttributeError:
                        logger.error('Not implemented Bacnet command')
                        self._response = None
                        return
            else:
                # Unrecognized services
                logger.info(
                    'Bacnet indication: Invalid unconfirmed service choice (%s)',
                    apdu_service)
                self._response_service = 'ErrorPDU'
                self._response = ErrorPDU()
                self._response.pduDestination = address
                return
        # ignore the following
        elif apdu_type.pduType == 0x2:
            # simple ack pdu
            self._response = None
            return
        elif apdu_type.pduType == 0x3:
            # complex ack pdu
            self._response = None
            return
        elif apdu_type.pduType == 0x4:
            # segment ack
            self._response = None
            return
        elif apdu_type.pduType == 0x5:
            # error pdu
            self._response = None
            return
        elif apdu_type.pduType == 0x6:
            # reject pdu
            self._response = None
            return
        elif apdu_type.pduType == 0x7:
            # abort pdu
            self._response = None
            return
        elif 0x8 <= apdu_type.pduType <= 0xf:
            # reserved
            self._response = None
            return
        else:
            # non-BACnet PDU types
            logger.info('Bacnet Unrecognized service')
            self._response = None
            return
Beispiel #2
0
def decode_packet(data, destination):
    """decode the data, return some kind of PDU."""
    if _debug:
        decode_packet._debug("decode_packet %r %r", data, destination)

    # build a PDU
    pdu = PDU(data, destination=destination)

    # check for a BVLL header
    if pdu.pduData[0] == 0x84:
        if _debug:
            decode_packet._debug("    - BVLL header found")

        xpdu = BVLPDU()
        xpdu.decode(pdu)
        pdu = xpdu

        # make a more focused interpretation
        atype = bvl_pdu_types.get(pdu.bvlciFunction)
        if not atype:
            if _debug:
                decode_packet._debug("    - unknown BVLL type: %r", pdu.bvlciFunction)
            return pdu

        # decode it as one of the basic types
        try:
            xpdu = pdu
            bpdu = atype()
            bpdu.decode(pdu)
            if _debug:
                decode_packet._debug("    - bpdu: %r", bpdu)

            pdu = bpdu

            # source address in the packet
            pdu.pduSource = pdu.bvlciAddress

            # no deeper decoding for some
            if atype not in (OriginalUnicastNPDU, OriginalBroadcastNPDU):
                return pdu

        except Exception as err:
            if _debug:
                decode_packet._debug("    - decoding Error: %r", err)
            return xpdu

    # check for version number
    if pdu.pduData[0] != 0x01:
        if _debug:
            decode_packet._debug(
                "    - not a version 1 packet: %s...", btox(pdu.pduData[:30], ".")
            )
        return None

    # it's an NPDU
    try:
        npdu = NPDU()
        npdu.decode(pdu)
    except Exception as err:
        if _debug:
            decode_packet._debug("    - decoding Error: %r", err)
        return None

    # application or network layer message
    if npdu.npduNetMessage is None:
        if _debug:
            decode_packet._debug("    - not a network layer message, try as an APDU")

        # decode as a generic APDU
        try:
            xpdu = APDU()
            xpdu.decode(npdu)
            apdu = xpdu
        except Exception as err:
            if _debug:
                decode_packet._debug("    - decoding Error: %r", err)
            return npdu

        # "lift" the source and destination address
        if npdu.npduSADR:
            apdu.pduSource = npdu.npduSADR
        else:
            apdu.pduSource = npdu.pduSource
        if npdu.npduDADR:
            apdu.pduDestination = npdu.npduDADR
        else:
            apdu.pduDestination = npdu.pduDestination

        # make a more focused interpretation
        atype = apdu_types.get(apdu.apduType)
        if not atype:
            if _debug:
                decode_packet._debug("    - unknown APDU type: %r", apdu.apduType)
            return apdu

        # decode it as one of the basic types
        try:
            xpdu = apdu
            apdu = atype()
            apdu.decode(xpdu)
        except Exception as err:
            if _debug:
                decode_packet._debug("    - decoding Error: %r", err)
            return xpdu

        # decode it at the next level
        if isinstance(apdu, ConfirmedRequestPDU):
            atype = confirmed_request_types.get(apdu.apduService)
            if not atype:
                if _debug:
                    decode_packet._debug(
                        "    - no confirmed request decoder: %r", apdu.apduService
                    )
                return apdu

        elif isinstance(apdu, UnconfirmedRequestPDU):
            atype = unconfirmed_request_types.get(apdu.apduService)
            if not atype:
                if _debug:
                    decode_packet._debug(
                        "    - no unconfirmed request decoder: %r", apdu.apduService
                    )
                return apdu

        elif isinstance(apdu, SimpleAckPDU):
            atype = None

        elif isinstance(apdu, ComplexAckPDU):
            atype = complex_ack_types.get(apdu.apduService)
            if not atype:
                if _debug:
                    decode_packet._debug(
                        "    - no complex ack decoder: %r", apdu.apduService
                    )
                return apdu

        elif isinstance(apdu, SegmentAckPDU):
            atype = None

        elif isinstance(apdu, ErrorPDU):
            atype = error_types.get(apdu.apduService)
            if not atype:
                if _debug:
                    decode_packet._debug("    - no error decoder: %r", apdu.apduService)
                return apdu

        elif isinstance(apdu, RejectPDU):
            atype = None

        elif isinstance(apdu, AbortPDU):
            atype = None
        if _debug:
            decode_packet._debug("    - atype: %r", atype)

        # deeper decoding
        try:
            if atype:
                xpdu = apdu
                apdu = atype()
                apdu.decode(xpdu)
        except Exception as err:
            if _debug:
                decode_packet._debug("    - decoding error: %r", err)
            return xpdu

        # success
        return apdu

    else:
        # make a more focused interpretation
        ntype = npdu_types.get(npdu.npduNetMessage)
        if not ntype:
            if _debug:
                decode_packet._debug(
                    "    - no network layer decoder: %r", npdu.npduNetMessage
                )
            return npdu
        if _debug:
            decode_packet._debug("    - ntype: %r", ntype)

        # deeper decoding
        try:
            xpdu = npdu
            npdu = ntype()
            npdu.decode(xpdu)
        except Exception as err:
            if _debug:
                decode_packet._debug("    - decoding error: %r", err)
            return xpdu

        # success
        return npdu
Beispiel #3
0
    def indication(self, apdu, address, device):
        """logging the received PDU type and Service request"""
        request = None
        apdu_type = apdu_types.get(apdu.apduType)
        invoke_key = apdu.apduInvokeID
        logger.info('Bacnet PDU received from %s:%d. (%s)', address[0], address[1], apdu_type.__name__)
        if apdu_type.pduType == 0x0:
            # Confirmed request handling
            apdu_service = confirmed_request_types.get(apdu.apduService)
            logger.info('Bacnet indication from %s:%d. (%s)', address[0], address[1], apdu_service.__name__)
            try:
                request = apdu_service()
                request.decode(apdu)
            except (AttributeError, RuntimeError, InvalidParameterDatatype) as e:
                logger.warning('Bacnet indication: Invalid service. Error: %s' % e)
                return
            except bacpypes.errors.DecodingError:
                pass

            for key, value in list(ConfirmedServiceChoice.enumerations.items()):
                if apdu_service.serviceChoice == value:
                    try:
                        getattr(self, key)(
                            request, address, invoke_key, device)
                        break
                    except AttributeError:
                        logger.error('Not implemented Bacnet command')
                        self._response = None
                        return
            else:
                logger.info('Bacnet indication: Invalid confirmed service choice (%s)', apdu_service.__name__)
                self._response = None
                return

        # Unconfirmed request handling
        elif apdu_type.pduType == 0x1:
            apdu_service = unconfirmed_request_types.get(apdu.apduService)
            logger.info('Bacnet indication from %s:%d. (%s)', address[0], address[1], apdu_service.__name__)
            try:
                request = apdu_service()
                request.decode(apdu)
            except (AttributeError, RuntimeError):
                logger.exception('Bacnet indication: Invalid service.')
                self._response = None
                return
            except bacpypes.errors.DecodingError:
                pass

            for key, value in list(UnconfirmedServiceChoice.enumerations.items()):
                if apdu_service.serviceChoice == value:
                    try:
                        getattr(self, key)(
                            request, address, invoke_key, device)
                        break
                    except AttributeError:
                        logger.error('Not implemented Bacnet command')
                        self._response = None
                        return
            else:
                # Unrecognized services
                logger.info(
                    'Bacnet indication: Invalid unconfirmed service choice (%s)', apdu_service)
                self._response_service = 'ErrorPDU'
                self._response = ErrorPDU()
                self._response.pduDestination = address
                return
        # ignore the following
        elif apdu_type.pduType == 0x2:
            # simple ack pdu
            self._response = None
            return
        elif apdu_type.pduType == 0x3:
            # complex ack pdu
            self._response = None
            return
        elif apdu_type.pduType == 0x4:
            # segment ack
            self._response = None
            return
        elif apdu_type.pduType == 0x5:
            # error pdu
            self._response = None
            return
        elif apdu_type.pduType == 0x6:
            # reject pdu
            self._response = None
            return
        elif apdu_type.pduType == 0x7:
            # abort pdu
            self._response = None
            return
        elif 0x8 <= apdu_type.pduType <= 0xf:
            # reserved
            self._response = None
            return
        else:
            # non-BACnet PDU types
            logger.info('Bacnet Unrecognized service')
            self._response = None
            return
        except Exception, err:
            if _debug: decode_packet._debug("    - decoding Error: %r", err)
            return xpdu

        # decode it at the next level
        if isinstance(apdu, ConfirmedRequestPDU):
            atype = confirmed_request_types.get(apdu.apduService)
            if not atype:
                if _debug:
                    decode_packet._debug(
                        "    - no confirmed request decoder: %r",
                        apdu.apduService)
                return apdu

        elif isinstance(apdu, UnconfirmedRequestPDU):
            atype = unconfirmed_request_types.get(apdu.apduService)
            if not atype:
                if _debug:
                    decode_packet._debug(
                        "    - no unconfirmed request decoder: %r",
                        apdu.apduService)
                return apdu

        elif isinstance(apdu, SimpleAckPDU):
            atype = None

        elif isinstance(apdu, ComplexAckPDU):
            atype = complex_ack_types.get(apdu.apduService)
            if not atype:
                if _debug:
                    decode_packet._debug("    - no complex ack decoder: %r",