Esempio n. 1
0
    def parse(self, data, negotiated):
        if not data:
            return self

        # We do not care if the attribute are transitive or not as we do not redistribute
        flag = Attribute.Flag(ord(data[0]))
        aid = Attribute.CODE(ord(data[1]))

        if flag & Attribute.Flag.EXTENDED_LENGTH:
            length = unpack('!H', data[2:4])[0]
            offset = 4
        else:
            length = ord(data[2])
            offset = 3

        data = data[offset:]
        left = data[length:]
        attribute = data[:length]

        logger = Logger()
        logger.parser(
            LazyFormat(
                "parsing flag %x type %02x (%s) len %02x %s" %
                (flag, int(aid), aid, length, 'payload ' if length else ''),
                data[:length]))

        # remove the PARTIAL bit before comparaison if the attribute is optional
        if aid in Attribute.attributes_optional:
            aid &= Attribute.Flag.MASK_PARTIAL & 0xFF
            # aid &= ~Attribute.Flag.PARTIAL & 0xFF  # cleaner than above (python use signed integer for ~)

        # handle the attribute if we know it
        if Attribute.registered(aid, flag):
            self.add(Attribute.unpack(aid, flag, attribute, negotiated))
            return self.parse(left, negotiated)
        # XXX: FIXME: we could use a fallback function here like capability

        # if we know the attribute but the flag is not what the RFC says. ignore it.
        if aid in Attribute.attributes_known:
            logger.parser(
                'invalid flag for attribute %s (flag 0x%02X, aid 0x%02X)' %
                (Attribute.CODE.names.get(aid, 'unset'), flag, aid))
            return self.parse(left, negotiated)

        # it is an unknown transitive attribute we need to pass on
        if flag & Attribute.Flag.TRANSITIVE:
            logger.parser(
                'unknown transitive attribute (flag 0x%02X, aid 0x%02X)' %
                (flag, aid))
            self.add(
                GenericAttribute(aid, flag | Attribute.Flag.PARTIAL,
                                 attribute), attribute)
            return self.parse(left, negotiated)

        # it is an unknown non-transitive attribute we can ignore.
        logger.parser(
            'ignoring unknown non-transitive attribute (flag 0x%02X, aid 0x%02X)'
            % (flag, aid))
        return self.parse(left, negotiated)
Esempio n. 2
0
    def flag_attribute_content(data):
        flag = Attribute.Flag(ord(data[0]))
        attr = Attribute.CODE(ord(data[1]))

        if flag & Attribute.Flag.EXTENDED_LENGTH:
            length = unpack('!H', data[2:4])[0]
            return flag, attr, data[4:length + 4]
        else:
            length = ord(data[2])
            return flag, attr, data[3:length + 3]
Esempio n. 3
0
    def add(self, attribute, _=None):
        # we return None as attribute if the unpack code must not generate them
        if attribute is None:
            return

        self._str = ''
        self._json = ''

        # XXX: FIXME: I am not sure anymore that more than one of each is possible
        if attribute.ID in Attributes.MULTIPLE:
            # deadcode: setdefault does not seem to exist anywhere ? (TM)
            self.setdefault(attribute.ID, []).append(attribute)
        # elif attribute.ID in (Attribute.CODE.COMMUNITY, Attribute.CODE.EXTENDED_COMMUNITY):
        # 	if attribute.ID not in self:
        # 		self[attribute.ID] = Attribute.klass(attribute.ID,attribute.FLAG)()
        # 	self[attribute.ID].add(attribute)
        elif attribute.ID in self:
            # For flows we can add extended-communities using special keywords and extended-community
            # This allows this trick
            if attribute.ID != Attribute.CODE.EXTENDED_COMMUNITY:
                raise Notify(
                    3, 0, 'multiple attribute for %s' %
                    str(Attribute.CODE(attribute.ID)))
            for community in attribute.communities:
                self[attribute.ID].add(community)
        else:
            self[attribute.ID] = attribute
Esempio n. 4
0
	def parse (self, data, negotiated):
		if not data:
			return self

		# We do not care if the attribute are transitive or not as we do not redistribute
		flag = Attribute.Flag(ord(data[0]))
		aid = Attribute.CODE(ord(data[1]))

		if flag & Attribute.Flag.EXTENDED_LENGTH:
			length = unpack('!H',data[2:4])[0]
			offset = 4
		else:
			length = ord(data[2])
			offset = 3

		data = data[offset:]
		left = data[length:]
		attribute = data[:length]

		logger = Logger()
		logger.parser(LazyFormat("parsing flag %x type %02x (%s) len %02x %s" % (flag,int(aid),aid,length,'payload ' if length else ''),data[:length]))

		# remove the PARTIAL bit before comparaison if the attribute is optional
		if aid in Attribute.attributes_optional:
			flag &= Attribute.Flag.MASK_PARTIAL & 0xFF
			# flag &= ~Attribute.Flag.PARTIAL & 0xFF  # cleaner than above (python use signed integer for ~)

		# handle the attribute if we know it
		if Attribute.registered(aid,flag):
			self.add(Attribute.unpack(aid,flag,attribute,negotiated))
			return self.parse(left,negotiated)
		# XXX: FIXME: we could use a fallback function here like capability

		# if we know the attribute but the flag is not what the RFC says. ignore it.
		if aid in Attribute.attributes_known:
			logger.parser('invalid flag for attribute %s (flag 0x%02X, aid 0x%02X)' % (Attribute.CODE.names.get(aid,'unset'),flag,aid))
			return self.parse(left,negotiated)

		# it is an unknown transitive attribute we need to pass on
		if flag & Attribute.Flag.TRANSITIVE:
			logger.parser('unknown transitive attribute (flag 0x%02X, aid 0x%02X)' % (flag,aid))
			self.add(GenericAttribute(aid,flag | Attribute.Flag.PARTIAL,attribute),attribute)
			return self.parse(left,negotiated)

		# it is an unknown non-transitive attribute we can ignore.
		logger.parser('ignoring unknown non-transitive attribute (flag 0x%02X, aid 0x%02X)' % (flag,aid))
		return self.parse(left,negotiated)
Esempio n. 5
0
    def add(self, attribute, _=None):
        # we return None as attribute if the unpack code must not generate them
        if attribute is None:
            return

        self._str = ''
        self._json = ''

        # XXX: FIXME: I am not sure anymore that more than one of each is possible
        if attribute.ID in Attributes.MULTIPLE:
            self.setdefault(attribute.ID, []).append(attribute)
        elif attribute.ID in self:
            raise Notify(
                3, 0, 'multiple attribute for %s' %
                str(Attribute.CODE(attribute.ID)))
        else:
            self[attribute.ID] = attribute
Esempio n. 6
0
    def add(self, attribute, data=None):
        # we return None as attribute if the unpack code must not generate them
        if attribute is None:
            return

        self._str = ''
        self._json = ''

        if attribute.MULTIPLE:
            if self.has(attribute.ID):
                self[attribute.ID].append(attribute)
            else:
                self[attribute.ID] = MultiAttributes(attribute)
        else:
            if attribute.ID in self:
                raise Notify(
                    3, 0, 'multiple attribute for %s' %
                    str(Attribute.ID(attribute.ID)))
            self[attribute.ID] = attribute
Esempio n. 7
0
    def parse(self, data, negotiated):
        if not data:
            return self

        try:
            # We do not care if the attribute are transitive or not as we do not redistribute
            flag = Attribute.Flag(ord(data[0]))
            aid = Attribute.CODE(ord(data[1]))
        except IndexError:
            self.add(TreatAsWithdraw())
            return self

        try:
            offset = 3
            length = ord(data[2])

            if flag & Attribute.Flag.EXTENDED_LENGTH:
                offset = 4
                length = (length << 8) + ord(data[3])
        except IndexError:
            self.add(TreatAsWithdraw(aid))
            return self

        data = data[offset:]
        left = data[length:]
        attribute = data[:length]

        logger = Logger()
        logger.parser(LazyAttribute(flag, aid, length, data[:length]))

        # remove the PARTIAL bit before comparaison if the attribute is optional
        if aid in Attribute.attributes_optional:
            flag &= Attribute.Flag.MASK_PARTIAL & 0xFF
            # flag &= ~Attribute.Flag.PARTIAL & 0xFF  # cleaner than above (python use signed integer for ~)

        if aid in self:
            if aid in self.NO_DUPLICATE:
                raise Notify(
                    3, 1, 'multiple attribute for %s' %
                    str(Attribute.CODE(attribute.ID)))

            logger.parser(
                'duplicate attribute %s (flag 0x%02X, aid 0x%02X) skipping' %
                (Attribute.CODE.names.get(aid, 'unset'), flag, aid))
            return self.parse(left, negotiated)

        # handle the attribute if we know it
        if Attribute.registered(aid, flag):
            if length == 0 and aid not in self.VALID_ZERO:
                self.add(TreatAsWithdraw(aid))
                return self.parse(left, negotiated)

            try:
                decoded = Attribute.unpack(aid, flag, attribute, negotiated)
            except IndexError, exc:
                if aid in self.TREAT_AS_WITHDRAW:
                    decoded = TreatAsWithdraw(aid)
                else:
                    raise exc
            except Notify, exc:
                if aid in self.TREAT_AS_WITHDRAW:
                    decoded = TreatAsWithdraw()
                elif aid in self.DISCARD:
                    decoded = Discard()
                else:
                    raise exc
Esempio n. 8
0
    def parse(self, data, direction, negotiated):
        if not data:
            return self

        try:
            # We do not care if the attribute are transitive or not as we do not redistribute
            flag = Attribute.Flag(data[0])
            aid = Attribute.CODE(data[1])
        except IndexError:
            self.add(TreatAsWithdraw())
            return self

        try:
            offset = 3
            length = data[2]

            if flag & Attribute.Flag.EXTENDED_LENGTH:
                offset = 4
                length = (length << 8) + data[3]
        except IndexError:
            self.add(TreatAsWithdraw(aid))
            return self

        data = data[offset:]
        left = data[length:]
        attribute = data[:length]

        logfunc.debug(lazyattribute(flag, aid, length, data[:length]), 'parser')

        # remove the PARTIAL bit before comparaison if the attribute is optional
        if aid in Attribute.attributes_optional:
            flag &= Attribute.Flag.MASK_PARTIAL & 0xFF
            # flag &= ~Attribute.Flag.PARTIAL & 0xFF  # cleaner than above (python use signed integer for ~)

        if aid in self:
            if aid in self.NO_DUPLICATE:
                raise Notify(3, 1, 'multiple attribute for %s' % str(Attribute.CODE(attribute.ID)))

            log.debug(
                'duplicate attribute %s (flag 0x%02X, aid 0x%02X) skipping'
                % (Attribute.CODE.names.get(aid, 'unset'), flag, aid),
                'parser',
            )
            return self.parse(left, direction, negotiated)

        # handle the attribute if we know it
        if Attribute.registered(aid, flag):
            if length == 0 and aid not in self.VALID_ZERO:
                self.add(TreatAsWithdraw(aid))
                return self.parse(left, direction, negotiated)

            try:
                decoded = Attribute.unpack(aid, flag, attribute, direction, negotiated)
            except IndexError as exc:
                if aid in self.TREAT_AS_WITHDRAW:
                    decoded = TreatAsWithdraw(aid)
                else:
                    raise exc
            except Notify as exc:
                if aid in self.TREAT_AS_WITHDRAW:
                    decoded = TreatAsWithdraw()
                elif aid in self.DISCARD:
                    decoded = Discard()
                else:
                    raise exc
            self.add(decoded)
            return self.parse(left, direction, negotiated)

        # XXX: FIXME: we could use a fallback function here like capability

        # if we know the attribute but the flag is not what the RFC says.
        if aid in Attribute.attributes_known:
            if aid in self.TREAT_AS_WITHDRAW:
                log.debug(
                    'invalid flag for attribute %s (flag 0x%02X, aid 0x%02X) treat as withdraw'
                    % (Attribute.CODE.names.get(aid, 'unset'), flag, aid),
                    'parser',
                )
                self.add(TreatAsWithdraw())
            if aid in self.DISCARD:
                log.debug(
                    'invalid flag for attribute %s (flag 0x%02X, aid 0x%02X) discard'
                    % (Attribute.CODE.names.get(aid, 'unset'), flag, aid),
                    'parser',
                )
                return self.parse(left, direction, negotiated)
            # XXX: Check if we are missing any
            log.debug(
                'invalid flag for attribute %s (flag 0x%02X, aid 0x%02X) unspecified (should not happen)'
                % (Attribute.CODE.names.get(aid, 'unset'), flag, aid),
                'parser',
            )
            return self.parse(left, direction, negotiated)

        # it is an unknown transitive attribute we need to pass on
        if flag & Attribute.Flag.TRANSITIVE:
            log.debug('unknown transitive attribute (flag 0x%02X, aid 0x%02X)' % (flag, aid), 'parser')
            try:
                decoded = GenericAttribute(aid, flag | Attribute.Flag.PARTIAL, attribute)
            except IndexError:
                decoded = TreatAsWithdraw(aid)
            self.add(decoded, attribute)
            return self.parse(left, direction, negotiated)

        # it is an unknown non-transitive attribute we can ignore.
        log.debug('ignoring unknown non-transitive attribute (flag 0x%02X, aid 0x%02X)' % (flag, aid), 'parser')
        return self.parse(left, direction, negotiated)
Esempio n. 9
0
from exabgp.bgp.message.update.attribute.med import MED
from exabgp.bgp.message.update.attribute.localpref import LocalPreference
from exabgp.bgp.message.update.attribute.atomicaggregate import AtomicAggregate
from exabgp.bgp.message.update.attribute.aggregator import Aggregator
from exabgp.bgp.message.update.attribute.aggregator import Aggregator4
from exabgp.bgp.message.update.attribute.community.communities import Communities
from exabgp.bgp.message.update.attribute.community.extended.communities import ExtendedCommunities
from exabgp.bgp.message.update.attribute.originatorid import OriginatorID
from exabgp.bgp.message.update.attribute.clusterlist import ClusterList
from exabgp.bgp.message.update.attribute.mprnlri import MPRNLRI
from exabgp.bgp.message.update.attribute.mpurnlri import MPURNLRI
from exabgp.bgp.message.update.attribute.pmsi import PMSI
from exabgp.bgp.message.update.attribute.aigp import AIGP
from exabgp.bgp.message.update.attribute.bgpsec import BGPSEC

Attribute.register_attribute(Origin)
Attribute.register_attribute(ASPath)
Attribute.register_attribute(AS4Path)
Attribute.register_attribute(NextHop)
Attribute.register_attribute(MED)
Attribute.register_attribute(LocalPreference)
Attribute.register_attribute(AtomicAggregate)
Attribute.register_attribute(Aggregator)
Attribute.register_attribute(Aggregator4)
Attribute.register_attribute(Communities)
Attribute.register_attribute(ExtendedCommunities)
Attribute.register_attribute(OriginatorID)
Attribute.register_attribute(ClusterList)
Attribute.register_attribute(MPRNLRI)
Attribute.register_attribute(MPURNLRI)
Attribute.register_attribute(PMSI)
Esempio n. 10
0
from exabgp.bgp.message.update.attribute.med import MED
from exabgp.bgp.message.update.attribute.localpref import LocalPreference
from exabgp.bgp.message.update.attribute.atomicaggregate import AtomicAggregate
from exabgp.bgp.message.update.attribute.aggregator import Aggregator
from exabgp.bgp.message.update.attribute.aggregator import Aggregator4
from exabgp.bgp.message.update.attribute.community.communities import Communities
from exabgp.bgp.message.update.attribute.community.extended.communities import ExtendedCommunities
from exabgp.bgp.message.update.attribute.originatorid import OriginatorID
from exabgp.bgp.message.update.attribute.clusterlist import ClusterList
from exabgp.bgp.message.update.attribute.mprnlri import MPRNLRI
from exabgp.bgp.message.update.attribute.mpurnlri import MPURNLRI
from exabgp.bgp.message.update.attribute.pmsi import PMSI
from exabgp.bgp.message.update.attribute.aigp import AIGP


Attribute.register_attribute(Origin)
Attribute.register_attribute(ASPath)
Attribute.register_attribute(AS4Path)
Attribute.register_attribute(NextHop)
Attribute.register_attribute(MED)
Attribute.register_attribute(LocalPreference)
Attribute.register_attribute(AtomicAggregate)
Attribute.register_attribute(Aggregator)
Attribute.register_attribute(Aggregator4)
Attribute.register_attribute(Communities)
Attribute.register_attribute(ExtendedCommunities)
Attribute.register_attribute(OriginatorID)
Attribute.register_attribute(ClusterList)
Attribute.register_attribute(MPRNLRI)
Attribute.register_attribute(MPURNLRI)
Attribute.register_attribute(PMSI)
Esempio n. 11
0
	def parse (self, data, negotiated):
		if not data:
			return self

		try:
			# We do not care if the attribute are transitive or not as we do not redistribute
			flag = Attribute.Flag(ordinal(data[0]))
			aid = Attribute.CODE(ordinal(data[1]))
		except IndexError:
			self.add(TreatAsWithdraw())
			return self

		try:
			offset = 3
			length = ordinal(data[2])

			if flag & Attribute.Flag.EXTENDED_LENGTH:
				offset = 4
				length = (length << 8) + ordinal(data[3])
		except IndexError:
			self.add(TreatAsWithdraw(aid))
			return self

		data = data[offset:]
		left = data[length:]
		attribute = data[:length]

		logger = Logger()
		logger.debug(LazyAttribute(flag,aid,length,data[:length]),'parser')

		# remove the PARTIAL bit before comparaison if the attribute is optional
		if aid in Attribute.attributes_optional:
			flag &= Attribute.Flag.MASK_PARTIAL & 0xFF
			# flag &= ~Attribute.Flag.PARTIAL & 0xFF  # cleaner than above (python use signed integer for ~)

		if aid in self:
			if aid in self.NO_DUPLICATE:
				raise Notify(3,1,'multiple attribute for %s' % str(Attribute.CODE(attribute.ID)))

			logger.debug('duplicate attribute %s (flag 0x%02X, aid 0x%02X) skipping' % (Attribute.CODE.names.get(aid,'unset'),flag,aid),'parser')
			return self.parse(left,negotiated)

		# handle the attribute if we know it
		if Attribute.registered(aid,flag):
			if length == 0 and aid not in self.VALID_ZERO:
				self.add(TreatAsWithdraw(aid))
				return self.parse(left,negotiated)

			try:
				decoded = Attribute.unpack(aid,flag,attribute,negotiated)
			except IndexError as exc:
				if aid in self.TREAT_AS_WITHDRAW:
					decoded = TreatAsWithdraw(aid)
				else:
					raise exc
			except Notify as exc:
				if aid in self.TREAT_AS_WITHDRAW:
					decoded = TreatAsWithdraw()
				elif aid in self.DISCARD:
					decoded = Discard()
				else:
					raise exc
			self.add(decoded)
			return self.parse(left,negotiated)

		# XXX: FIXME: we could use a fallback function here like capability

		# if we know the attribute but the flag is not what the RFC says.
		if aid in Attribute.attributes_known:
			if aid in self.TREAT_AS_WITHDRAW:
				logger.debug('invalid flag for attribute %s (flag 0x%02X, aid 0x%02X) treat as withdraw' % (Attribute.CODE.names.get(aid,'unset'),flag,aid),'parser')
				self.add(TreatAsWithdraw())
			if aid in self.DISCARD:
				logger.debug('invalid flag for attribute %s (flag 0x%02X, aid 0x%02X) discard' % (Attribute.CODE.names.get(aid,'unset'),flag,aid),'parser')
				return self.parse(left,negotiated)
			# XXX: Check if we are missing any
			logger.debug('invalid flag for attribute %s (flag 0x%02X, aid 0x%02X) unspecified (should not happen)' % (Attribute.CODE.names.get(aid,'unset'),flag,aid),'parser')
			return self.parse(left,negotiated)

		# it is an unknown transitive attribute we need to pass on
		if flag & Attribute.Flag.TRANSITIVE:
			logger.debug('unknown transitive attribute (flag 0x%02X, aid 0x%02X)' % (flag,aid),'parser')
			try:
				decoded = GenericAttribute(aid,flag | Attribute.Flag.PARTIAL,attribute)
			except IndexError:
				decoded = TreatAsWithdraw(aid)
			self.add(decoded,attribute)
			return self.parse(left,negotiated)

		# it is an unknown non-transitive attribute we can ignore.
		logger.debug('ignoring unknown non-transitive attribute (flag 0x%02X, aid 0x%02X)' % (flag,aid),'parser')
		return self.parse(left,negotiated)
Esempio n. 12
0
	def parse (self, data, negotiated):
		if not data:
			return self

		try:
			# We do not care if the attribute are transitive or not as we do not redistribute
			flag = Attribute.Flag(ord(data[0]))
			aid = Attribute.CODE(ord(data[1]))
		except IndexError:
			self.add(TreatAsWithdraw())
			return self

		try:
			offset = 3
			length = ord(data[2])

			if flag & Attribute.Flag.EXTENDED_LENGTH:
				offset = 4
				length = (length << 8) + ord(data[3])
		except IndexError:
			self.add(TreatAsWithdraw(aid))
			return self

		data = data[offset:]
		left = data[length:]
		attribute = data[:length]

		logger = Logger()
		logger.parser(LazyAttribute(flag,aid,length,data[:length]))

		# remove the PARTIAL bit before comparaison if the attribute is optional
		if aid in Attribute.attributes_optional:
			flag &= Attribute.Flag.MASK_PARTIAL & 0xFF
			# flag &= ~Attribute.Flag.PARTIAL & 0xFF  # cleaner than above (python use signed integer for ~)

		if aid in self:
			if aid in self.NO_DUPLICATE:
				raise Notify(3,1,'multiple attribute for %s' % str(Attribute.CODE(attribute.ID)))

			logger.parser('duplicate attribute %s (flag 0x%02X, aid 0x%02X) skipping' % (Attribute.CODE.names.get(aid,'unset'),flag,aid))
			return self.parse(left,negotiated)

		# handle the attribute if we know it
		if Attribute.registered(aid,flag):
			if length == 0 and aid not in self.VALID_ZERO:
				self.add(TreatAsWithdraw(aid))
				return self.parse(left,negotiated)

			try:
				decoded = Attribute.unpack(aid,flag,attribute,negotiated)
			except IndexError, exc:
				if aid in self.TREAT_AS_WITHDRAW:
					decoded = TreatAsWithdraw(aid)
				else:
					raise exc
			except Notify, exc:
				if aid in self.TREAT_AS_WITHDRAW:
					decoded = TreatAsWithdraw()
				elif aid in self.DISCARD:
					decoded = Discard()
				else:
					raise exc