예제 #1
0
 def __init__(self,
              packed,
              nexthop=NoNextHop,
              action=OUT.UNSET,
              addpath=None):
     NLRI.__init__(self, AFI.l2vpn, SAFI.evpn, action)
     self.nexthop = nexthop
     self._packed = packed
예제 #2
0
def check_nlri(neighbor, routes):
    option.enabled['parser'] = True

    announced = _hexa(routes)
    negotiated = _negotiated(neighbor)

    afi, safi = neighbor.families()[0]

    # Is the peer going to send us some Path Information with the route (AddPath)
    addpath = negotiated.addpath.send(afi, safi)

    nlris = []
    try:
        while announced:
            log.debug('parsing NLRI %s' % announced, 'parser')
            nlri, announced = NLRI.unpack_nlri(afi, safi, announced, IN.ANNOUNCED, addpath)
            nlris.append(nlri)
    except Exception as exc:
        log.error('could not parse the nlri', 'parser')
        from exabgp.debug import string_exception
        log.error(string_exception(exc), 'parser')
        if getenv().debug.pdb:
            raise
        return False

    log.debug('', 'parser')  # new line
    for nlri in nlris:
        log.info('nlri json %s' % nlri.json(), 'parser')
    return True
예제 #3
0
def _negotiated(neighbor):
    path = {}
    for f in NLRI.known_families():
        if neighbor['capability']['add-path']:
            path[f] = neighbor['capability']['add-path']

    capa = Capabilities().new(neighbor, False)
    capa[Capability.CODE.ADD_PATH] = path
    capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families()
    # capa[Capability.CODE.FOUR_BYTES_ASN] = True

    routerid_1 = str(neighbor['router-id'])
    routerid_2 = '.'.join(
        str((int(_) + 1) % 250)
        for _ in str(neighbor['router-id']).split('.', -1))

    o1 = Open(Version(4), ASN(neighbor['local-as']), HoldTime(180),
              RouterID(routerid_1), capa)
    o2 = Open(Version(4), ASN(neighbor['peer-as']), HoldTime(180),
              RouterID(routerid_2), capa)
    negotiated = Negotiated(neighbor)
    negotiated.sent(o1)
    negotiated.received(o2)
    # grouped = False
    return negotiated
예제 #4
0
    def unpack(cls, data, direction, negotiated):
        nlris = []

        # -- Reading AFI/SAFI
        afi, safi = unpack('!HB', data[:3])
        offset = 3
        data = data[offset:]

        if negotiated and (afi, safi) not in negotiated.families:
            raise Notify(
                3, 0, 'presented a non-negotiated family %s %s' %
                (AFI.create(afi), SAFI.create(safi)))

        # Do we need to handle Path Information with the route (AddPath)
        if direction == Direction.IN:
            addpath = negotiated.addpath.receive(afi, safi)
        else:
            addpath = negotiated.addpath.send(afi, safi)

        while data:
            nlri, data = NLRI.unpack_nlri(afi, safi, data, IN.WITHDRAWN,
                                          addpath)
            # allow unpack_nlri to return none for "treat as withdraw" controlled by NLRI.unpack_nlri
            if nlri:
                nlris.append(nlri)

        return cls(afi, safi, nlris)
예제 #5
0
파일: check.py 프로젝트: Shmuma/exabgp
def check_update (neighbor, raw):
	logger = Logger()
	logger._option.parser = True
	logger.parser('\ndecoding routes in configuration')


	neighbor = neighbor[neighbor.keys()[0]]

	path = {}
	for f in NLRI.known_families():
		if neighbor.add_path:
			path[f] = neighbor.add_path

	capa = Capabilities().new(neighbor,False)
	capa[Capability.CODE.ADD_PATH] = path
	capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families()
	# capa[Capability.CODE.FOUR_BYTES_ASN] = True

	routerid_1 = str(neighbor.router_id)
	routerid_2 = '.'.join(str((int(_)+1) % 250) for _ in str(neighbor.router_id).split('.',-1))

	o1 = Open(4,neighbor.local_as,routerid_1,capa,180)
	o2 = Open(4,neighbor.peer_as,routerid_2,capa,180)
	negotiated = Negotiated(neighbor)
	negotiated.sent(o1)
	negotiated.received(o2)
	# grouped = False

	while raw:
		if raw.startswith('\xff'*16):
			kind = ord(raw[18])
			size = (ord(raw[16]) << 16) + (ord(raw[17]))

			injected,raw = raw[19:size],raw[size:]

			if kind == 2:
				logger.parser('the message is an update')
				decoding = 'update'
			else:
				logger.parser('the message is not an update (%d) - aborting' % kind)
				return False
		else:
			logger.parser('header missing, assuming this message is ONE update')
			decoding = 'update'
			injected,raw = raw,''

		try:
			# This does not take the BGP header - let's assume we will not break that :)
			update = Update.unpack_message(injected,negotiated)
		except KeyboardInterrupt:
			raise
		except Notify,exc:
			logger.parser('could not parse the message')
			logger.parser(str(exc))
			return False
		except Exception,exc:
			logger.parser('could not parse the message')
			logger.parser(str(exc))
			return False
예제 #6
0
	def __eq__ (self, other):
		return \
			NLRI.__eq__(self,other) and \
			self.CODE == other.CODE and \
			self.rd == other.rd and \
			self.etag == other.etag and \
			self.ip == other.ip and \
			self.iplen == other.iplen
예제 #7
0
	def __eq__ (self, other):
		return \
			NLRI.__eq__(self,other) and \
			self.CODE == other.CODE and \
			self.rd == other.rd and \
			self.etag == other.etag and \
			self.ip == other.ip and \
			self.iplen == other.iplen
예제 #8
0
파일: mpurnlri.py 프로젝트: aabdnn/exabgp
	def unpack (cls, data, negotiated):
		nlris = []

		# -- Reading AFI/SAFI
		afi,safi = unpack('!HB',data[:3])
		offset = 3
		data = data[offset:]

		if negotiated and (afi,safi) not in negotiated.families:
			raise Notify(3,0,'presented a non-negotiated family %s %s' % (AFI.create(afi),SAFI.create(safi)))

		# Is the peer going to send us some Path Information with the route (AddPath)
		addpath = negotiated.addpath.receive(afi,safi)

		while data:
			nlri,data = NLRI.unpack_nlri(afi,safi,data,IN.WITHDRAWN,addpath)
			nlris.append(nlri)

		return cls(afi,safi,nlris)
예제 #9
0
	def unpack (cls, data, negotiated):
		nlris = []

		# -- Reading AFI/SAFI
		afi,safi = unpack('!HB',data[:3])
		offset = 3
		data = data[offset:]

		if negotiated and (afi,safi) not in negotiated.families:
			raise Notify(3,0,'presented a non-negotiated family %s %s' % (AFI.create(afi),SAFI.create(safi)))

		# Is the peer going to send us some Path Information with the route (AddPath)
		addpath = negotiated.addpath.receive(afi,safi)

		while data:
			nlri,data = NLRI.unpack_nlri(afi,safi,data,IN.WITHDRAWN,addpath)
			nlris.append(nlri)

		return cls(afi,safi,nlris)
예제 #10
0
	def unpack (cls, data, negotiated):
		nlris = []

		# -- Reading AFI/SAFI
		afi,safi = unpack('!HB',data[:3])
		offset = 3
		data = data[offset:]

		if negotiated and (afi,safi) not in negotiated.families:
			raise Notify(3,0,'presented a non-negotiated family %s %s' % (AFI(afi),SAFI(safi)))

		# Is the peer going to send us some Path Information with the route (AddPath)
		addpath = negotiated.addpath.receive(afi,safi)

		while data:
			length,nlri = NLRI.unpack(afi,safi,data,addpath,None,IN.WITHDRAWN)
			nlris.append(nlri)
			data = data[length:]
			# logger.parser(LazyFormat("parsed withdraw mp nlri %s payload " % nlri,data[:length]))

		return cls(afi,safi,nlris)
예제 #11
0
    def unpack(cls, data, negotiated):
        nlris = []

        # -- Reading AFI/SAFI
        afi, safi = unpack('!HB', data[:3])
        offset = 3
        data = data[offset:]

        if negotiated and (afi, safi) not in negotiated.families:
            raise Notify(
                3, 0, 'presented a non-negotiated family %s %s' %
                (AFI(afi), SAFI(safi)))

        # Is the peer going to send us some Path Information with the route (AddPath)
        addpath = negotiated.addpath.receive(afi, safi)

        while data:
            length, nlri = NLRI.unpack(afi, safi, data, addpath, None,
                                       IN.WITHDRAWN)
            nlris.append(nlri)
            data = data[length:]
            # logger.parser(LazyFormat("parsed withdraw mp nlri %s payload " % nlri,data[:length]))

        return cls(afi, safi, nlris)
예제 #12
0
 def families():
     return NLRI.known_families()
예제 #13
0
파일: eor.py 프로젝트: xiaopeng163/exabgp
		def __init__ (self, afi, safi, action):
			_NLRI.__init__(self,afi,safi)
			self.action = action
예제 #14
0
    def unpack_message(cls, data, negotiated):
        logger = Logger()

        length = len(data)

        # This could be speed up massively by changing the order of the IF
        if length == 23:
            return EOR(AFI.ipv4, SAFI.unicast, IN.ANNOUNCED)  # pylint: disable=E1101
        if length == 30 and data.startswith(EOR.NLRI.PREFIX):
            return EOR.unpack_message(data, negotiated)

        withdrawn, _attributes, announced = cls.split(data)
        attributes = Attributes.unpack(_attributes, negotiated)

        if not withdrawn:
            logger.parser("no withdrawn NLRI")
        if not announced:
            logger.parser("no announced NLRI")

        # Is the peer going to send us some Path Information with the route (AddPath)
        addpath = negotiated.addpath.receive(AFI(AFI.ipv4), SAFI(SAFI.unicast))

        # empty string for NoNextHop, the packed IP otherwise (without the 3/4 bytes of attributes headers)
        _nexthop = attributes.get(Attribute.CODE.NEXT_HOP, NoNextHop)
        nexthop = _nexthop.packed

        # XXX: NEXTHOP MUST NOT be the IP address of the receiving speaker.

        nlris = []
        while withdrawn:
            length, nlri = NLRI.unpack(AFI.ipv4, SAFI.unicast, withdrawn,
                                       addpath, nexthop, IN.WITHDRAWN)
            logger.parser(
                LazyFormat("parsed withdraw nlri %s payload " % nlri,
                           withdrawn[:len(nlri)]))
            withdrawn = withdrawn[length:]
            nlris.append(nlri)

        while announced:
            length, nlri = NLRI.unpack(AFI.ipv4, SAFI.unicast, announced,
                                       addpath, nexthop, IN.ANNOUNCED)
            logger.parser(
                LazyFormat("parsed announce nlri %s payload " % nlri,
                           announced[:len(nlri)]))
            announced = announced[length:]
            nlris.append(nlri)

        # required for 'is' comparaison
        UNREACH = [
            EMPTY_MPURNLRI,
        ]
        REACH = [
            EMPTY_MPRNLRI,
        ]

        unreach = attributes.pop(MPURNLRI.ID, UNREACH)
        reach = attributes.pop(MPRNLRI.ID, REACH)

        for mpr in unreach:
            nlris.extend(mpr.nlris)

        for mpr in reach:
            nlris.extend(mpr.nlris)

        if not attributes and not nlris:
            # Careful do not use == or != as the comparaison does not work
            if unreach is UNREACH and reach is REACH:
                return EOR(AFI(AFI.ipv4), SAFI(SAFI.unicast))
            if unreach is not UNREACH:
                return EOR(unreach[0].afi, unreach[0].safi)
            if reach is not REACH:
                return EOR(reach[0].afi, reach[0].safi)
            raise RuntimeError('This was not expected')

        return Update(nlris, attributes)
예제 #15
0
    def unpack(cls, data, negotiated):
        nlris = []

        # -- Reading AFI/SAFI
        afi, safi = unpack('!HB', data[:3])
        offset = 3

        # we do not want to accept unknown families
        if negotiated and (afi, safi) not in negotiated.families:
            raise Notify(
                3, 0, 'presented a non-negotiated family %d/%d' % (afi, safi))

        # -- Reading length of next-hop
        len_nh = ord(data[offset])
        offset += 1

        rd = 0

        # check next-hop size
        if afi == AFI.ipv4:
            if safi in (SAFI.unicast, SAFI.multicast):
                if len_nh != 4:
                    raise Notify(
                        3, 0,
                        'invalid ipv4 unicast/multicast next-hop length %d expected 4'
                        % len_nh)
            elif safi in (SAFI.mpls_vpn, ):
                if len_nh != 12:
                    raise Notify(
                        3, 0,
                        'invalid ipv4 mpls_vpn next-hop length %d expected 12'
                        % len_nh)
                rd = 8
            elif safi in (SAFI.flow_ip, ):
                if len_nh not in (0, 4):
                    raise Notify(
                        3, 0,
                        'invalid ipv4 flow_ip next-hop length %d expected 4' %
                        len_nh)
            elif safi in (SAFI.flow_vpn, ):
                if len_nh not in (0, 4):
                    raise Notify(
                        3, 0,
                        'invalid ipv4 flow_vpn next-hop length %d expected 4' %
                        len_nh)
            elif safi in (SAFI.rtc, ):
                if len_nh not in (4, 16):
                    raise Notify(
                        3, 0,
                        'invalid ipv4 rtc next-hop length %d expected 4' %
                        len_nh)
        elif afi == AFI.ipv6:
            if safi in (SAFI.unicast, ):
                if len_nh not in (16, 32):
                    raise Notify(
                        3, 0,
                        'invalid ipv6 unicast next-hop length %d expected 16 or 32'
                        % len_nh)
            elif safi in (SAFI.mpls_vpn, ):
                if len_nh not in (24, 40):
                    raise Notify(
                        3, 0,
                        'invalid ipv6 mpls_vpn next-hop length %d expected 24 or 40'
                        % len_nh)
                rd = 8
            elif safi in (SAFI.flow_ip, ):
                if len_nh not in (0, 16, 32):
                    raise Notify(
                        3, 0,
                        'invalid ipv6 flow_ip next-hop length %d expected 0, 16 or 32'
                        % len_nh)
            elif safi in (SAFI.flow_vpn, ):
                if len_nh not in (0, 16, 32):
                    raise Notify(
                        3, 0,
                        'invalid ipv6 flow_vpn next-hop length %d expected 0, 16 or 32'
                        % len_nh)
        elif afi == AFI.l2vpn:
            if len_nh != 4:
                Notify(3, 0,
                       'invalid l2vpn next-hop length %d expected 4' % len_nh)
        elif afi == AFI.bgpls:
            if len_nh != 4:
                Notify(3, 0,
                       'invalid bgpls next-hop length %d expected 4' % len_nh)
        size = len_nh - rd

        # XXX: FIXME: GET IT FROM CACHE HERE ?
        nhs = data[offset + rd:offset + rd + size]
        nexthops = [nhs[pos:pos + 16] for pos in range(0, len(nhs), 16)]

        # chech the RD is well zero
        if rd and sum([int(ord(_)) for _ in data[offset:8]]) != 0:
            raise Notify(
                3, 0,
                "MP_REACH_NLRI next-hop's route-distinguisher must be zero")

        offset += len_nh

        # Skip a reserved bit as somone had to bug us !
        reserved = ord(data[offset])
        offset += 1

        if reserved != 0:
            raise Notify(3, 0, 'the reserved bit of MP_REACH_NLRI is not zero')

        # Is the peer going to send us some Path Information with the route (AddPath)
        addpath = negotiated.addpath.receive(afi, safi)

        # Reading the NLRIs
        data = data[offset:]

        if not data:
            raise Notify(
                3, 0,
                'No data to decode in an MPREACHNLRI but it is not an EOR %d/%d'
                % (afi, safi))

        while data:
            if nexthops:
                for nexthop in nexthops:
                    nlri, left = NLRI.unpack_nlri(afi, safi, data,
                                                  IN.ANNOUNCED, addpath)
                    nlri.nexthop = NextHop.unpack(nexthop)
                    nlris.append(nlri)
            else:
                nlri, left = NLRI.unpack_nlri(afi, safi, data, IN.ANNOUNCED,
                                              addpath)
                nlris.append(nlri)

            if left == data:
                raise RuntimeError("sub-calls should consume data")

            # logger.parser(LazyFormat("parsed announce mp nlri %s payload " % nlri,data[:length]))
            data = left
        return cls(afi, safi, nlris)
예제 #16
0
파일: nlri.py 프로젝트: bopopescu/exabgp-1
 def __eq__(self, other):
     return NLRI.__eq__(self, other) and self.CODE == other.CODE
예제 #17
0
파일: check.py 프로젝트: benagricola/exabgp
def check_update (neighbor, raw):
	logger = Logger()
	logger._option.parser = True
	logger.parser('\ndecoding routes in configuration')

	neighbor = neighbor[neighbor.keys()[0]]

	path = {}
	for f in NLRI.known_families():
		if neighbor.add_path:
			path[f] = neighbor.add_path

	capa = Capabilities().new(neighbor,False)
	capa[Capability.CODE.ADD_PATH] = path
	capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families()
	# capa[Capability.CODE.FOUR_BYTES_ASN] = True

	routerid_1 = str(neighbor.router_id)
	routerid_2 = '.'.join(str((int(_)+1) % 250) for _ in str(neighbor.router_id).split('.',-1))

	o1 = Open(Version(4),ASN(neighbor.local_as),HoldTime(180),RouterID(routerid_1),capa)
	o2 = Open(Version(4),ASN(neighbor.peer_as),HoldTime(180),RouterID(routerid_2),capa)
	negotiated = Negotiated(neighbor)
	negotiated.sent(o1)
	negotiated.received(o2)
	# grouped = False

	while raw:
		if raw.startswith('\xff'*16):
			kind = ord(raw[18])
			size = (ord(raw[16]) << 16) + (ord(raw[17]))

			injected,raw = raw[19:size],raw[size:]

			if kind == 2:
				logger.parser('the message is an update')
				decoding = 'update'
			else:
				logger.parser('the message is not an update (%d) - aborting' % kind)
				return False
		else:
			logger.parser('header missing, assuming this message is ONE update')
			decoding = 'update'
			injected,raw = raw,''

		try:
			# This does not take the BGP header - let's assume we will not break that :)
			update = Update.unpack_message(injected,negotiated)
		except KeyboardInterrupt:
			raise
		except Notify:
			logger.parser('could not parse the message','error')
			logger.parser(traceback.format_exc(),'error')
			return False
		except StandardError:
			logger.parser('could not parse the message','error')
			logger.parser(traceback.format_exc(),'error')
			return False

		logger.parser('')  # new line
		for number in range(len(update.nlris)):
			change = Change(update.nlris[number],update.attributes)
			logger.parser('decoded %s %s %s' % (decoding,change.nlri.action,change.extensive()))
		logger.parser('update json %s' % Response.JSON(json_version).update(neighbor,'in',update,'',''))

	return True
예제 #18
0
파일: nlri.py 프로젝트: Exa-Networks/exabgp
	def __init__(self, action=OUT.UNSET, addpath=None):
		NLRI.__init__(self, AFI.bgpls, SAFI.bgp_ls, action)
		self._packed = b''
예제 #19
0
	def unpack_message (cls, data, negotiated):
		logger = Logger()

		length = len(data)

		# This could be speed up massively by changing the order of the IF
		if length == 4 and data == '\x00\x00\x00\x00':
			return EOR(AFI.ipv4,SAFI.unicast,IN.ANNOUNCED)  # pylint: disable=E1101
		if length == 11 and data.startswith(EOR.NLRI.PREFIX):
			return EOR.unpack_message(data,negotiated)

		withdrawn, _attributes, announced = cls.split(data)
		attributes = Attributes.unpack(_attributes,negotiated)

		if not withdrawn:
			logger.parser("no withdrawn NLRI")
		if not announced:
			logger.parser("no announced NLRI")

		# Is the peer going to send us some Path Information with the route (AddPath)
		addpath = negotiated.addpath.receive(AFI(AFI.ipv4),SAFI(SAFI.unicast))

		# empty string for NoNextHop, the packed IP otherwise (without the 3/4 bytes of attributes headers)
		nexthop = attributes.get(Attribute.CODE.NEXT_HOP,NoNextHop)
		# nexthop = NextHop.unpack(_nexthop.ton())

		# XXX: NEXTHOP MUST NOT be the IP address of the receiving speaker.

		nlris = []
		while withdrawn:
			nlri,left = NLRI.unpack_nlri(AFI.ipv4,SAFI.unicast,withdrawn,IN.WITHDRAWN,addpath)
			logger.parser(LazyFormat("parsed withdraw nlri %s payload " % nlri,withdrawn[:len(nlri)]))
			withdrawn = left
			nlris.append(nlri)

		while announced:
			nlri,left = NLRI.unpack_nlri(AFI.ipv4,SAFI.unicast,announced,IN.ANNOUNCED,addpath)
			nlri.nexthop = nexthop
			logger.parser(LazyFormat("parsed announce nlri %s payload " % nlri,announced[:len(nlri)]))
			announced = left
			nlris.append(nlri)

		# required for 'is' comparaison
		UNREACH = [EMPTY_MPURNLRI,]
		REACH = [EMPTY_MPRNLRI,]

		unreach = attributes.pop(MPURNLRI.ID,UNREACH)
		reach = attributes.pop(MPRNLRI.ID,REACH)

		for mpr in unreach:
			nlris.extend(mpr.nlris)

		for mpr in reach:
			nlris.extend(mpr.nlris)

		if not attributes and not nlris:
			# Careful do not use == or != as the comparaison does not work
			if unreach is UNREACH and reach is REACH:
				return EOR(AFI(AFI.ipv4),SAFI(SAFI.unicast))
			if unreach is not UNREACH:
				return EOR(unreach[0].afi,unreach[0].safi)
			if reach is not REACH:
				return EOR(reach[0].afi,reach[0].safi)
			raise RuntimeError('This was not expected')

		return Update(nlris,attributes)
예제 #20
0
파일: nlri.py 프로젝트: szhong-jnpr/exabgp
	def index(self):
		return NLRI._index(self) + self.pack()
예제 #21
0
 def __init__(self, packed, nexthop, action, path=None):
     NLRI.__init__(self, AFI.l2vpn, SAFI.evpn)
     self.nexthop = IP.unpack(nexthop) if nexthop else NoNextHop
     self.action = action
     self.packed = packed
예제 #22
0
파일: check.py 프로젝트: waders909/exabgp
def check_generation(neighbors):
    option.enabled['parser'] = True

    for name in neighbors.keys():
        neighbor = copy.deepcopy(neighbors[name])
        neighbor['local-as'] = neighbor['peer-as']

        path = {}
        for f in NLRI.known_families():
            if neighbor['capability']['add-path']:
                path[f] = neighbor['capability']['add-path']

        capa = Capabilities().new(neighbor, False)
        if path:
            capa[Capability.CODE.ADD_PATH] = path
        capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families()

        routerid_1 = str(neighbor['router-id'])
        routerid_2 = '.'.join(
            str((int(_) + 1) % 250)
            for _ in str(neighbor['router-id']).split('.', -1))

        o1 = Open(Version(4), ASN(neighbor['local-as']), HoldTime(180),
                  RouterID(routerid_1), capa)
        o2 = Open(Version(4), ASN(neighbor['peer-as']), HoldTime(180),
                  RouterID(routerid_2), capa)
        negotiated = Negotiated(neighbor)
        negotiated.sent(o1)
        negotiated.received(o2)
        # grouped = False

        for _ in neighbor.rib.outgoing.updates(False):
            pass

        for change1 in neighbor.rib.outgoing.cached_changes():
            str1 = change1.extensive()
            packed = list(
                Update([change1.nlri],
                       change1.attributes).messages(negotiated))
            pack1 = packed[0]

            log.debug('parsed route requires %d updates' % len(packed),
                      'parser')
            log.debug('update size is %d' % len(pack1), 'parser')

            log.debug('parsed route %s' % str1, 'parser')
            log.debug('parsed hex   %s' % od(pack1), 'parser')

            # This does not take the BGP header - let's assume we will not break that :)
            try:
                log.debug('')  # new line

                pack1s = pack1[19:] if pack1.startswith(b'\xFF' *
                                                        16) else pack1
                update = Update.unpack_message(pack1s, negotiated)

                change2 = Change(update.nlris[0], update.attributes)
                str2 = change2.extensive()
                pack2 = list(
                    Update([update.nlris[0]],
                           update.attributes).messages(negotiated))[0]

                log.debug('recoded route %s' % str2, 'parser')
                log.debug('recoded hex   %s' % od(pack2), 'parser')

                str1 = str1.replace('attribute [ 0x04 0x80 0x00000064 ]',
                                    'med 100')
                str1r = (str1.lower().replace(' med 100', '').replace(
                    ' local-preference 100', '').replace(' origin igp', ''))
                str2r = (str2.lower().replace(' med 100', '').replace(
                    ' local-preference 100', '').replace(' origin igp', ''))
                str2r = str2r.replace(
                    'large-community [ 1:2:3 10:11:12 ]',
                    'attribute [ 0x20 0xc0 0x0000000100000002000000030000000a0000000b0000000c ]',
                )

                if 'next-hop self' in str1r:
                    if ':' in str1r:
                        str1r = str1r.replace('next-hop self', 'next-hop ::1')
                    else:
                        str1r = str1r.replace(
                            'next-hop self',
                            'next-hop %s' % neighbor['local-address'])

                if ' name ' in str1r:
                    parts = str1r.split(' ')
                    pos = parts.index('name')
                    str1r = ' '.join(parts[:pos] + parts[pos + 2:])

                skip = False

                if str1r != str2r:
                    if 'attribute [' in str1r and ' 0x00 ' in str1r:
                        # we do not decode non-transitive attributes
                        log.debug(
                            'skipping string check on update with non-transitive attribute(s)',
                            'parser')
                        skip = True
                    else:
                        log.debug('strings are different:', 'parser')
                        log.debug('[%s]' % (str1r), 'parser')
                        log.debug('[%s]' % (str2r), 'parser')
                        return False
                else:
                    log.debug('strings are fine', 'parser')

                if skip:
                    log.debug(
                        'skipping encoding for update with non-transitive attribute(s)',
                        'parser')
                elif pack1 != pack2:
                    log.debug('encoding are different', 'parser')
                    log.debug('[%s]' % (od(pack1)), 'parser')
                    log.debug('[%s]' % (od(pack2)), 'parser')
                    return False
                else:
                    log.debug('encoding is fine', 'parser')
                    log.debug('----------------------------------------',
                              'parser')

                log.debug('JSON nlri %s' % change1.nlri.json(), 'parser')
                log.debug('JSON attr %s' % change1.attributes.json(), 'parser')

            except Notify as exc:
                log.debug('----------------------------------------', 'parser')
                log.debug(str(exc), 'parser')
                log.debug('----------------------------------------', 'parser')
                return False
        neighbor.rib.clear()

    return True
예제 #23
0
def check_update(neighbor, raw):
    logger = Logger()
    logger._option.parser = True
    logger.parser('\ndecoding routes in configuration')

    neighbor = neighbor[neighbor.keys()[0]]

    path = {}
    for f in NLRI.known_families():
        if neighbor.add_path:
            path[f] = neighbor.add_path

    capa = Capabilities().new(neighbor, False)
    capa[Capability.CODE.ADD_PATH] = path
    capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families()
    # capa[Capability.CODE.FOUR_BYTES_ASN] = True

    routerid_1 = str(neighbor.router_id)
    routerid_2 = '.'.join(
        str((int(_) + 1) % 250)
        for _ in str(neighbor.router_id).split('.', -1))

    o1 = Open(Version(4), ASN(neighbor.local_as), HoldTime(180),
              RouterID(routerid_1), capa)
    o2 = Open(Version(4), ASN(neighbor.peer_as), HoldTime(180),
              RouterID(routerid_2), capa)
    negotiated = Negotiated(neighbor)
    negotiated.sent(o1)
    negotiated.received(o2)
    # grouped = False

    while raw:
        if raw.startswith('\xff' * 16):
            kind = ord(raw[18])
            size = (ord(raw[16]) << 16) + (ord(raw[17]))

            injected, raw = raw[19:size], raw[size:]

            if kind == 2:
                logger.parser('the message is an update')
                decoding = 'update'
            else:
                logger.parser('the message is not an update (%d) - aborting' %
                              kind)
                return False
        else:
            logger.parser(
                'header missing, assuming this message is ONE update')
            decoding = 'update'
            injected, raw = raw, ''

        try:
            # This does not take the BGP header - let's assume we will not break that :)
            update = Update.unpack_message(injected, negotiated)
        except KeyboardInterrupt:
            raise
        except Notify:
            logger.parser('could not parse the message', 'error')
            logger.parser(traceback.format_exc(), 'error')
            return False
        except StandardError:
            logger.parser('could not parse the message', 'error')
            logger.parser(traceback.format_exc(), 'error')
            return False

        logger.parser('')  # new line
        for number in range(len(update.nlris)):
            change = Change(update.nlris[number], update.attributes)
            logger.parser('decoded %s %s %s' %
                          (decoding, change.nlri.action, change.extensive()))
        logger.parser(
            'update json %s' %
            Response.JSON(json_version).update(neighbor, 'in', update, '', ''))

    return True
예제 #24
0
파일: eor.py 프로젝트: tempbottle/exabgp
 def __init__(self, afi, safi, action):
     _NLRI.__init__(self, afi, safi, action)
     self.action = action
예제 #25
0
파일: nlri.py 프로젝트: earies/exabgp
	def __init__ (self, packed, nexthop, action, path=None):
		NLRI.__init__(self, AFI.l2vpn, SAFI.evpn)
		self.nexthop = IP.unpack(nexthop) if nexthop else NoNextHop
		self.action = action
		self._packed = packed
예제 #26
0
 def __init__(self, action=OUT.UNSET, addpath=None):
     NLRI.__init__(self, AFI.bgpls, SAFI.bgp_ls, action)
     self._packed = b''
예제 #27
0
    def unpack_message(cls, data, negotiated):
        logger = Logger()

        logger.debug(LazyFormat('parsing UPDATE', data), 'parser')

        length = len(data)

        # This could be speed up massively by changing the order of the IF
        if length == 4 and data == b'\x00\x00\x00\x00':
            return EOR(AFI.ipv4, SAFI.unicast)  # pylint: disable=E1101
        if length == 11 and data.startswith(EOR.NLRI.PREFIX):
            return EOR.unpack_message(data, negotiated)

        withdrawn, _attributes, announced = cls.split(data)

        if not withdrawn:
            logger.debug('withdrawn NLRI none', 'routes')

        attributes = Attributes.unpack(_attributes, negotiated)

        if not announced:
            logger.debug('announced NLRI none', 'routes')

        # Is the peer going to send us some Path Information with the route (AddPath)
        addpath = negotiated.addpath.receive(AFI.ipv4, SAFI.unicast)

        # empty string for NoNextHop, the packed IP otherwise (without the 3/4 bytes of attributes headers)
        nexthop = attributes.get(Attribute.CODE.NEXT_HOP, NoNextHop)
        # nexthop = NextHop.unpack(_nexthop.ton())

        # XXX: NEXTHOP MUST NOT be the IP address of the receiving speaker.

        nlris = []
        while withdrawn:
            nlri, left = NLRI.unpack_nlri(AFI.ipv4, SAFI.unicast, withdrawn,
                                          IN.WITHDRAWN, addpath)
            logger.debug('withdrawn NLRI %s' % nlri, 'routes')
            withdrawn = left
            nlris.append(nlri)

        while announced:
            nlri, left = NLRI.unpack_nlri(AFI.ipv4, SAFI.unicast, announced,
                                          IN.ANNOUNCED, addpath)
            nlri.nexthop = nexthop
            logger.debug('announced NLRI %s' % nlri, 'routes')
            announced = left
            nlris.append(nlri)

        unreach = attributes.pop(MPURNLRI.ID, None)
        reach = attributes.pop(MPRNLRI.ID, None)

        if unreach is not None:
            nlris.extend(unreach.nlris)

        if reach is not None:
            nlris.extend(reach.nlris)

        if not attributes and not nlris:
            # Careful do not use == or != as the comparaison does not work
            if unreach is None and reach is None:
                return EOR(AFI.ipv4, SAFI.unicast)
            if unreach is not None:
                return EOR(unreach.afi, unreach.safi)
            if reach is not None:
                return EOR(reach.afi, reach.safi)
            raise RuntimeError('This was not expected')

        update = Update(nlris, attributes)

        def parsed(_):
            # we need the import in the function as otherwise we have an cyclic loop
            # as this function currently uses Update..
            from exabgp.reactor.api.response import Response
            from exabgp.version import json as json_version
            return 'json %s' % Response.JSON(json_version).update(
                negotiated.neighbor, 'in', update, None, '', '')

        logger.debug(LazyFormat('decoded UPDATE', '', parsed), 'parser')

        return update
예제 #28
0
	def families ():
		return NLRI.known_families()
예제 #29
0
파일: nlri.py 프로젝트: qoke/exabgp
 def index(self):
     return NLRI._index(self) + self.pack()
예제 #30
0
파일: check.py 프로젝트: benagricola/exabgp
def check_neighbor (neighbors):
	logger = Logger()
	logger._option.parser = True

	logger.parser('\ndecoding routes in configuration')

	for name in neighbors.keys():
		neighbor = neighbors[name]

		path = {}
		for f in NLRI.known_families():
			if neighbor.add_path:
				path[f] = neighbor.add_path

		capa = Capabilities().new(neighbor,False)
		if path:
			capa[Capability.CODE.ADD_PATH] = path
		capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families()

		routerid_1 = str(neighbor.router_id)
		routerid_2 = '.'.join(str((int(_)+1) % 250) for _ in str(neighbor.router_id).split('.',-1))

		o1 = Open(Version(4),ASN(neighbor.local_as),HoldTime(180),RouterID(routerid_1),capa)
		o2 = Open(Version(4),ASN(neighbor.peer_as),HoldTime(180),RouterID(routerid_2),capa)
		negotiated = Negotiated(neighbor)
		negotiated.sent(o1)
		negotiated.received(o2)
		# grouped = False

		for _ in neighbor.rib.outgoing.updates(False):
			pass

		for change1 in neighbor.rib.outgoing.sent_changes():
			str1 = change1.extensive()
			packed = list(Update([change1.nlri],change1.attributes).messages(negotiated))
			pack1 = packed[0]

			logger.parser('parsed route requires %d updates' % len(packed))
			logger.parser('update size is %d' % len(pack1))

			logger.parser('parsed route %s' % str1)
			logger.parser('parsed hex   %s' % od(pack1))

			# This does not take the BGP header - let's assume we will not break that :)
			try:
				logger.parser('')  # new line

				pack1s = pack1[19:] if pack1.startswith('\xFF'*16) else pack1
				update = Update.unpack_message(pack1s,negotiated)

				change2 = Change(update.nlris[0],update.attributes)
				str2 = change2.extensive()
				pack2 = list(Update([update.nlris[0]],update.attributes).messages(negotiated))[0]

				logger.parser('recoded route %s' % str2)
				logger.parser('recoded hex   %s' % od(pack2))

				str1 = str1.replace('attribute [ 0x04 0x80 0x00000064 ]','med 100')
				str1r = str1.lower().replace(' med 100','').replace(' local-preference 100','').replace(' origin igp','')
				str2r = str2.lower().replace(' med 100','').replace(' local-preference 100','').replace(' origin igp','')

				if 'next-hop self' in str1r:
					if ':' in str1r:
						str1r = str1r.replace('next-hop self','next-hop ::1')
					else:
						str1r = str1r.replace('next-hop self','next-hop %s' % neighbor.local_address)

				if ' name ' in str1r:
					parts = str1r.split(' ')
					pos = parts.index('name')
					str1r = ' '.join(parts[:pos] + parts[pos+2:])

				skip = False

				if str1r != str2r:
					if 'attribute [' in str1r and ' 0x00 ' in str1r:
						# we do not decode non-transitive attributes
						logger.parser('skipping string check on update with non-transitive attribute(s)')
						skip = True
					else:
						logger.parser('strings are different:')
						logger.parser('[%s]' % (str1r))
						logger.parser('[%s]' % (str2r))
						return False
				else:
					logger.parser('strings are fine')

				if skip:
					logger.parser('skipping encoding for update with non-transitive attribute(s)')
				elif pack1 != pack2:
					logger.parser('encoding are different')
					logger.parser('[%s]' % (od(pack1)))
					logger.parser('[%s]' % (od(pack2)))
					return False
				else:
					logger.parser('encoding is fine')
					logger.parser('----------------------------------------')

				logger.parser('JSON nlri %s' % change1.nlri.json())
				logger.parser('JSON attr %s' % change1.attributes.json())

			except Notify,exc:
				logger.parser('----------------------------------------')
				logger.parser(str(exc))
				logger.parser('----------------------------------------')
				return False
		neighbor.rib.clear()
예제 #31
0
	def unpack (cls, data, negotiated):
		nlris = []

		# -- Reading AFI/SAFI
		afi,safi = unpack('!HB',data[:3])
		offset = 3

		# we do not want to accept unknown families
		if negotiated and (afi,safi) not in negotiated.families:
			raise Notify(3,0,'presented a non-negotiated family %d/%d' % (afi,safi))

		# -- Reading length of next-hop
		len_nh = ord(data[offset])
		offset += 1

		rd = 0

		# check next-hop size
		if afi == AFI.ipv4:
			if safi in (SAFI.unicast,SAFI.multicast):
				if len_nh != 4:
					raise Notify(3,0,'invalid ipv4 unicast/multicast next-hop length %d expected 4' % len_nh)
			elif safi in (SAFI.mpls_vpn,):
				if len_nh != 12:
					raise Notify(3,0,'invalid ipv4 mpls_vpn next-hop length %d expected 12' % len_nh)
				rd = 8
			elif safi in (SAFI.flow_ip,):
				if len_nh not in (0,4):
					raise Notify(3,0,'invalid ipv4 flow_ip next-hop length %d expected 4' % len_nh)
			elif safi in (SAFI.flow_vpn,):
				if len_nh not in (0,4):
					raise Notify(3,0,'invalid ipv4 flow_vpn next-hop length %d expected 4' % len_nh)
			elif safi in (SAFI.rtc,):
				if len_nh not in (4,16):
					raise Notify(3,0,'invalid ipv4 rtc next-hop length %d expected 4' % len_nh)
		elif afi == AFI.ipv6:
			if safi in (SAFI.unicast,):
				if len_nh not in (16,32):
					raise Notify(3,0,'invalid ipv6 unicast next-hop length %d expected 16 or 32' % len_nh)
			elif safi in (SAFI.mpls_vpn,):
				if len_nh not in (24,40):
					raise Notify(3,0,'invalid ipv6 mpls_vpn next-hop length %d expected 24 or 40' % len_nh)
				rd = 8
			elif safi in (SAFI.flow_ip,):
				if len_nh not in (0,16,32):
					raise Notify(3,0,'invalid ipv6 flow_ip next-hop length %d expected 0, 16 or 32' % len_nh)
			elif safi in (SAFI.flow_vpn,):
				if len_nh not in (0,16,32):
					raise Notify(3,0,'invalid ipv6 flow_vpn next-hop length %d expected 0, 16 or 32' % len_nh)
		elif afi == AFI.l2vpn:
			if len_nh != 4:
				Notify(3,0,'invalid l2vpn next-hop length %d expected 4' % len_nh)
		size = len_nh - rd

		# XXX: FIXME: GET IT FROM CACHE HERE ?
		nhs = data[offset+rd:offset+rd+size]
		nexthops = [nhs[pos:pos+16] for pos in range(0,len(nhs),16)]

		# chech the RD is well zero
		if rd and sum([int(ord(_)) for _ in data[offset:8]]) != 0:
			raise Notify(3,0,"MP_REACH_NLRI next-hop's route-distinguisher must be zero")

		offset += len_nh

		# Skip a reserved bit as somone had to bug us !
		reserved = ord(data[offset])
		offset += 1

		if reserved != 0:
			raise Notify(3,0,'the reserved bit of MP_REACH_NLRI is not zero')

		# Is the peer going to send us some Path Information with the route (AddPath)
		addpath = negotiated.addpath.receive(afi,safi)

		# Reading the NLRIs
		data = data[offset:]

		if not data:
			raise Notify(3,0,'No data to decode in an MPREACHNLRI but it is not an EOR %d/%d' % (afi,safi))

		while data:
			if nexthops:
				for nexthop in nexthops:
					length,nlri = NLRI.unpack(afi,safi,data,addpath,nexthop,IN.ANNOUNCED)
					nlris.append(nlri)
			else:
				length,nlri = NLRI.unpack(afi,safi,data,addpath,'',IN.ANNOUNCED)
				nlris.append(nlri)

			if length == 0:
				raise RuntimeError("sub-calls should not return length zero")

			# logger.parser(LazyFormat("parsed announce mp nlri %s payload " % nlri,data[:length]))
			data = data[length:]
		return cls(afi,safi,nlris)
예제 #32
0
    def unpack(cls, data, negotiated):
        nlris = []

        # -- Reading AFI/SAFI
        _afi, _safi = unpack('!HB', data[:3])
        afi, safi = AFI.create(_afi), SAFI.create(_safi)
        offset = 3

        # we do not want to accept unknown families
        if negotiated and (afi, safi) not in negotiated.families:
            raise Notify(
                3, 0, 'presented a non-negotiated family %s/%s' % (afi, safi))

        # -- Reading length of next-hop
        len_nh = ordinal(data[offset])
        offset += 1

        if (afi, safi) not in Family.size:
            raise Notify(3, 0, 'unsupported %s %s' % (afi, safi))

        length, rd = Family.size[(afi, safi)]

        if len_nh not in length:
            raise Notify(
                3, 0, 'invalid %s %s next-hop length %d expected %s' %
                (afi, safi, len_nh, ' or '.join(str(_) for _ in length)))

        size = len_nh - rd

        # XXX: FIXME: GET IT FROM CACHE HERE ?
        nhs = data[offset + rd:offset + rd + size]
        nexthops = [nhs[pos:pos + 16] for pos in range(0, len(nhs), 16)]

        # chech the RD is well zero
        if rd and sum([int(ordinal(_)) for _ in data[offset:8]]) != 0:
            raise Notify(
                3, 0,
                "MP_REACH_NLRI next-hop's route-distinguisher must be zero")

        offset += len_nh

        # Skip a reserved bit as somone had to bug us !
        reserved = ordinal(data[offset])
        offset += 1

        if reserved != 0:
            raise Notify(3, 0, 'the reserved bit of MP_REACH_NLRI is not zero')

        # Is the peer going to send us some Path Information with the route (AddPath)
        addpath = negotiated.addpath.receive(afi, safi)

        # Reading the NLRIs
        data = data[offset:]

        if not data:
            raise Notify(
                3, 0,
                'No data to decode in an MPREACHNLRI but it is not an EOR %d/%d'
                % (afi, safi))

        while data:
            if nexthops:
                for nexthop in nexthops:
                    nlri, left = NLRI.unpack_nlri(afi, safi, data,
                                                  IN.ANNOUNCED, addpath)
                    # allow unpack_nlri to return none for "treat as withdraw" controlled by NLRI.unpack_nlri
                    if nlri:
                        nlri.nexthop = NextHop.unpack(nexthop)
                        nlris.append(nlri)
            else:
                nlri, left = NLRI.unpack_nlri(afi, safi, data, IN.ANNOUNCED,
                                              addpath)
                # allow unpack_nlri to return none for "treat as withdraw" controlled by NLRI.unpack_nlri
                if nlri:
                    nlris.append(nlri)

            if left == data:
                raise RuntimeError("sub-calls should consume data")

            data = left
        return cls(afi, safi, nlris)
예제 #33
0
파일: eor.py 프로젝트: Exa-Networks/exabgp
		def __init__ (self, afi, safi, action):
			_NLRI.__init__(self,afi,safi,action)
			self.action = action
			self.afi = afi
			self.safi = safi
예제 #34
0
파일: check.py 프로젝트: waders909/exabgp
def check_update(neighbor, raw):
    option.enabled['parser'] = True

    neighbor = neighbor[list(neighbor)[0]]

    path = {}
    for f in NLRI.known_families():
        if neighbor['capability']['add-path']:
            path[f] = neighbor['capability']['add-path']

    capa = Capabilities().new(neighbor, False)
    capa[Capability.CODE.ADD_PATH] = path
    capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families()
    # capa[Capability.CODE.FOUR_BYTES_ASN] = True

    routerid_1 = str(neighbor['router-id'])
    routerid_2 = '.'.join(
        str((int(_) + 1) % 250)
        for _ in str(neighbor['router-id']).split('.', -1))

    o1 = Open(Version(4), ASN(neighbor['local-as']), HoldTime(180),
              RouterID(routerid_1), capa)
    o2 = Open(Version(4), ASN(neighbor['peer-as']), HoldTime(180),
              RouterID(routerid_2), capa)
    negotiated = Negotiated(neighbor)
    negotiated.sent(o1)
    negotiated.received(o2)
    # grouped = False

    while raw:
        if raw.startswith(b'\xff' * 16):
            kind = raw[18]
            size = (raw[16] << 16) + raw[17]

            injected, raw = raw[19:size], raw[size:]

            if kind == 2:
                log.debug('the message is an update', 'parser')
                decoding = 'update'
            else:
                log.debug(
                    'the message is not an update (%d) - aborting' % kind,
                    'parser')
                return False
        else:
            log.debug('header missing, assuming this message is ONE update',
                      'parser')
            decoding = 'update'
            injected, raw = raw, ''

        try:
            # This does not take the BGP header - let's assume we will not break that :)
            update = Update.unpack_message(injected, negotiated)
        except Notify:
            import traceback

            log.error('could not parse the message', 'parser')
            log.error(traceback.format_exc(), 'parser')
            return False
        except Exception:
            import traceback

            log.error('could not parse the message', 'parser')
            log.error(traceback.format_exc(), 'parser')
            return False

        log.debug('', 'parser')  # new line
        for number in range(len(update.nlris)):
            change = Change(update.nlris[number], update.attributes)
            log.info(
                'decoded %s %s %s' %
                (decoding, change.nlri.action, change.extensive()), 'parser')
        log.info(
            'update json %s' % Response.JSON(json_version).update(
                neighbor, 'in', update, None, '', ''), 'parser')

    return True
예제 #35
0
파일: mprnlri.py 프로젝트: aabdnn/exabgp
	def unpack (cls, data, negotiated):
		nlris = []

		# -- Reading AFI/SAFI
		_afi,_safi = unpack('!HB',data[:3])
		afi,safi = AFI.create(_afi),SAFI.create(_safi)
		offset = 3

		# we do not want to accept unknown families
		if negotiated and (afi,safi) not in negotiated.families:
			raise Notify(3,0,'presented a non-negotiated family %s/%s' % (afi,safi))

		# -- Reading length of next-hop
		len_nh = ordinal(data[offset])
		offset += 1

		if (afi,safi) not in Family.size:
			raise Notify(3,0,'unsupported %s %s' % (afi,safi))

		length,rd = Family.size[(afi,safi)]

		if len_nh not in length:
			raise Notify(3,0,'invalid %s %s next-hop length %d expected %s' % (afi,safi,len_nh,' or '.join(str(_) for _ in length)))

		size = len_nh - rd

		# XXX: FIXME: GET IT FROM CACHE HERE ?
		nhs = data[offset+rd:offset+rd+size]
		nexthops = [nhs[pos:pos+16] for pos in range(0,len(nhs),16)]

		# chech the RD is well zero
		if rd and sum([int(ordinal(_)) for _ in data[offset:8]]) != 0:
			raise Notify(3,0,"MP_REACH_NLRI next-hop's route-distinguisher must be zero")

		offset += len_nh

		# Skip a reserved bit as somone had to bug us !
		reserved = ordinal(data[offset])
		offset += 1

		if reserved != 0:
			raise Notify(3,0,'the reserved bit of MP_REACH_NLRI is not zero')

		# Is the peer going to send us some Path Information with the route (AddPath)
		addpath = negotiated.addpath.receive(afi,safi)

		# Reading the NLRIs
		data = data[offset:]

		if not data:
			raise Notify(3,0,'No data to decode in an MPREACHNLRI but it is not an EOR %d/%d' % (afi,safi))

		while data:
			if nexthops:
				for nexthop in nexthops:
					nlri,left = NLRI.unpack_nlri(afi,safi,data,IN.ANNOUNCED,addpath)
					nlri.nexthop = NextHop.unpack(nexthop)
					nlris.append(nlri)
			else:
				nlri,left = NLRI.unpack_nlri(afi,safi,data,IN.ANNOUNCED,addpath)
				nlris.append(nlri)

			if left == data:
				raise RuntimeError("sub-calls should consume data")

			data = left
		return cls(afi,safi,nlris)
예제 #36
0
파일: __init__.py 프로젝트: leleobhz/exabgp
    def unpack_message(cls, data, negotiated):
        logger = Logger()

        logger.parser(LazyFormat("parsing UPDATE", data))

        length = len(data)

        # This could be speed up massively by changing the order of the IF
        if length == 4 and data == b'\x00\x00\x00\x00':
            return EOR(AFI(AFI.ipv4), SAFI(SAFI.unicast))  # pylint: disable=E1101
        if length == 11 and data.startswith(EOR.NLRI.PREFIX):
            return EOR.unpack_message(data, negotiated)

        withdrawn, _attributes, announced = cls.split(data)

        if not withdrawn:
            logger.parser("withdrawn NLRI none")

        attributes = Attributes.unpack(_attributes, negotiated)

        if not announced:
            logger.parser("announced NLRI none")

        # Is the peer going to send us some Path Information with the route (AddPath)
        addpath = negotiated.addpath.receive(AFI(AFI.ipv4), SAFI(SAFI.unicast))

        # empty string for NoNextHop, the packed IP otherwise (without the 3/4 bytes of attributes headers)
        nexthop = attributes.get(Attribute.CODE.NEXT_HOP, NoNextHop)
        # nexthop = NextHop.unpack(_nexthop.ton())

        # XXX: NEXTHOP MUST NOT be the IP address of the receiving speaker.

        nlris = []
        while withdrawn:
            nlri, left = NLRI.unpack_nlri(AFI.ipv4, SAFI.unicast, withdrawn,
                                          IN.WITHDRAWN, addpath)
            logger.parser("withdrawn NLRI %s" % nlri)
            withdrawn = left
            nlris.append(nlri)

        while announced:
            nlri, left = NLRI.unpack_nlri(AFI.ipv4, SAFI.unicast, announced,
                                          IN.ANNOUNCED, addpath)
            nlri.nexthop = nexthop
            logger.parser("announced NLRI %s" % nlri)
            announced = left
            nlris.append(nlri)

        unreach = attributes.pop(MPURNLRI.ID, None)
        reach = attributes.pop(MPRNLRI.ID, None)

        if unreach is not None:
            nlris.extend(unreach.nlris)

        if reach is not None:
            nlris.extend(reach.nlris)

        if not attributes and not nlris:
            # Careful do not use == or != as the comparaison does not work
            if unreach is None and reach is None:
                return EOR(AFI(AFI.ipv4), SAFI(SAFI.unicast))
            if unreach is not None:
                return EOR(unreach.afi, unreach.safi)
            if reach is not None:
                return EOR(reach.afi, reach.safi)
            raise RuntimeError('This was not expected')

        return Update(nlris, attributes)
예제 #37
0
파일: nlri.py 프로젝트: qz267/exabgp
 def __init__(self, packed, nexthop=NoNextHop, action=OUT.UNSET, addpath=None):
     NLRI.__init__(self, AFI.l2vpn, SAFI.evpn, action)
     self.nexthop = nexthop
     self._packed = packed
예제 #38
0
파일: nlri.py 프로젝트: szhong-jnpr/exabgp
	def __init__ (self, action=OUT.UNSET, addpath=None):
		NLRI.__init__(self, AFI.l2vpn, SAFI.evpn, action)
		self._packed = b''
예제 #39
0
def check_update(neighbor, raw):
    logger = Logger()
    logger._option.parser = True
    logger.parser('\ndecoding routes in configuration')

    neighbor = neighbor[neighbor.keys()[0]]

    path = {}
    for f in NLRI.known_families():
        if neighbor.add_path:
            path[f] = neighbor.add_path

    capa = Capabilities().new(neighbor, False)
    capa[Capability.CODE.ADD_PATH] = path
    capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families()
    # capa[Capability.CODE.FOUR_BYTES_ASN] = True

    routerid_1 = str(neighbor.router_id)
    routerid_2 = '.'.join(
        str((int(_) + 1) % 250)
        for _ in str(neighbor.router_id).split('.', -1))

    o1 = Open(4, neighbor.local_as, routerid_1, capa, 180)
    o2 = Open(4, neighbor.peer_as, routerid_2, capa, 180)
    negotiated = Negotiated(neighbor)
    negotiated.sent(o1)
    negotiated.received(o2)
    # grouped = False

    while raw:
        if raw.startswith('\xff' * 16):
            kind = ord(raw[18])
            size = (ord(raw[16]) << 16) + (ord(raw[17]))

            injected, raw = raw[19:size], raw[size:]

            if kind == 2:
                logger.parser('the message is an update')
                decoding = 'update'
            else:
                logger.parser('the message is not an update (%d) - aborting' %
                              kind)
                return False
        else:
            logger.parser(
                'header missing, assuming this message is ONE update')
            decoding = 'update'
            injected, raw = raw, ''

        try:
            # This does not take the BGP header - let's assume we will not break that :)
            update = Update.unpack_message(injected, negotiated)
        except KeyboardInterrupt:
            raise
        except Notify, exc:
            logger.parser('could not parse the message')
            logger.parser(str(exc))
            return False
        except Exception, exc:
            logger.parser('could not parse the message')
            logger.parser(str(exc))
            return False
예제 #40
0
파일: nlri.py 프로젝트: szhong-jnpr/exabgp
	def __eq__ (self, other):
		return \
			NLRI.__eq__(self,other) and \
			self.CODE == other.CODE and \
			self.pack() == other.pack()
예제 #41
0
def check_neighbor(neighbors):
    logger = Logger()
    logger._option.parser = True

    if not neighbors:
        logger.parser('\ncould not find neighbor(s) to check')
        return False

    logger.parser('\ndecoding routes in configuration')

    for name in neighbors.keys():
        neighbor = neighbors[name]

        path = {}
        for f in NLRI.known_families():
            if neighbor.add_path:
                path[f] = neighbor.add_path

        capa = Capabilities().new(neighbor, False)
        if path:
            capa[Capability.CODE.ADD_PATH] = path
        capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families()

        o1 = Open(4, neighbor.local_as, str(neighbor.local_address), capa, 180)
        o2 = Open(4, neighbor.peer_as, str(neighbor.peer_address), capa, 180)
        negotiated = Negotiated(neighbor)
        negotiated.sent(o1)
        negotiated.received(o2)
        # grouped = False

        for _ in neighbor.rib.outgoing.updates(False):
            pass

        for change1 in neighbor.rib.outgoing.sent_changes():
            str1 = change1.extensive()
            packed = list(
                Update([change1.nlri],
                       change1.attributes).messages(negotiated))
            pack1 = packed[0]

            logger.parser('parsed route requires %d updates' % len(packed))
            logger.parser('parsed route requires %d updates' % len(packed))
            logger.parser('update size is %d' % len(pack1))

            logger.parser('parsed route %s' % str1)
            logger.parser('parsed hex   %s' % od(pack1))

            # This does not take the BGP header - let's assume we will not break that :)
            try:
                logger.parser('')  # new line

                pack1s = pack1[19:] if pack1.startswith('\xFF' * 16) else pack1
                update = Update.unpack_message(pack1s, negotiated)

                change2 = Change(update.nlris[0], update.attributes)
                str2 = change2.extensive()
                pack2 = list(
                    Update([update.nlris[0]],
                           update.attributes).messages(negotiated))[0]

                logger.parser('recoded route %s' % str2)
                logger.parser('recoded hex   %s' % od(pack2))

                str1r = str1.replace(' med 100', '').replace(
                    ' local-preference 100', '').replace(' origin igp', '')
                str2r = str2.replace(' med 100', '').replace(
                    ' local-preference 100', '').replace(' origin igp', '')

                if ' name ' in str1r:
                    parts = str1r.split(' ')
                    pos = parts.index('name')
                    str1r = ' '.join(parts[:pos] + parts[pos + 2:])

                skip = False

                if str1r != str2r:
                    if 'attribute [' in str1r and ' 0x00 ' in str1r:
                        # we do not decode non-transitive attributes
                        logger.parser(
                            'skipping string check on update with non-transitive attribute(s)'
                        )
                        skip = True
                    else:
                        logger.parser('strings are different:')
                        logger.parser('[%s]' % (str1r))
                        logger.parser('[%s]' % (str2r))
                        return False
                else:
                    logger.parser('strings are fine')

                if skip:
                    logger.parser(
                        'skipping encoding for update with non-transitive attribute(s)'
                    )
                elif pack1 != pack2:
                    logger.parser('encoding are different')
                    logger.parser('[%s]' % (od(pack1)))
                    logger.parser('[%s]' % (od(pack2)))
                    return False
                else:
                    logger.parser('encoding is fine')
                    logger.parser('----------------------------------------')

                logger.parser('JSON nlri %s' % change1.nlri.json())
                logger.parser('JSON attr %s' % change1.attributes.json())

            except Notify, exc:
                logger.parser('----------------------------------------')
                logger.parser(str(exc))
                logger.parser('----------------------------------------')
                return False
        neighbor.rib.clear()
예제 #42
0
파일: nlri.py 프로젝트: qoke/exabgp
 def __init__(self, action=OUT.UNSET, addpath=None):
     NLRI.__init__(self, AFI.l2vpn, SAFI.evpn, action)
     self._packed = b''
예제 #43
0
 def exit(self, tokeniser):
     if Capability.CODE(Capability.CODE.MULTIPROTOCOL) not in self.content:
         self.content[Capability.CODE(
             Capability.CODE.MULTIPROTOCOL)] = MultiProtocol(
                 NLRI.known_families())
예제 #44
0
파일: nlri.py 프로젝트: qoke/exabgp
 def __eq__(self, other):
     return \
      NLRI.__eq__(self,other) and \
      self.CODE == other.CODE and \
      self.pack() == other.pack()
예제 #45
0
파일: __init__.py 프로젝트: aabdnn/exabgp
	def unpack_message (cls, data, negotiated):
		logger = Logger()

		logger.debug(LazyFormat('parsing UPDATE',data),'parser')

		length = len(data)

		# This could be speed up massively by changing the order of the IF
		if length == 4 and data == b'\x00\x00\x00\x00':
			return EOR(AFI.ipv4,SAFI.unicast)  # pylint: disable=E1101
		if length == 11 and data.startswith(EOR.NLRI.PREFIX):
			return EOR.unpack_message(data,negotiated)

		withdrawn, _attributes, announced = cls.split(data)

		if not withdrawn:
			logger.debug('withdrawn NLRI none','parser')

		attributes = Attributes.unpack(_attributes,negotiated)

		if not announced:
			logger.debug('announced NLRI none','parser')

		# Is the peer going to send us some Path Information with the route (AddPath)
		addpath = negotiated.addpath.receive(AFI.ipv4,SAFI.unicast)

		# empty string for NoNextHop, the packed IP otherwise (without the 3/4 bytes of attributes headers)
		nexthop = attributes.get(Attribute.CODE.NEXT_HOP,NoNextHop)
		# nexthop = NextHop.unpack(_nexthop.ton())

		# XXX: NEXTHOP MUST NOT be the IP address of the receiving speaker.

		nlris = []
		while withdrawn:
			nlri,left = NLRI.unpack_nlri(AFI.ipv4,SAFI.unicast,withdrawn,IN.WITHDRAWN,addpath)
			logger.debug('withdrawn NLRI %s' % nlri,'parser')
			withdrawn = left
			nlris.append(nlri)

		while announced:
			nlri,left = NLRI.unpack_nlri(AFI.ipv4,SAFI.unicast,announced,IN.ANNOUNCED,addpath)
			nlri.nexthop = nexthop
			logger.debug('announced NLRI %s' % nlri,'parser')
			announced = left
			nlris.append(nlri)

		unreach = attributes.pop(MPURNLRI.ID,None)
		reach = attributes.pop(MPRNLRI.ID,None)

		if unreach is not None:
			nlris.extend(unreach.nlris)

		if reach is not None:
			nlris.extend(reach.nlris)

		if not attributes and not nlris:
			# Careful do not use == or != as the comparaison does not work
			if unreach is None and reach is None:
				return EOR(AFI.ipv4,SAFI.unicast)
			if unreach is not None:
				return EOR(unreach.afi,unreach.safi)
			if reach is not None:
				return EOR(reach.afi,reach.safi)
			raise RuntimeError('This was not expected')

		return Update(nlris,attributes)
예제 #46
0
 def __init__(self, afi, safi, action):
     _NLRI.__init__(self, afi, safi, action)
     self.action = action
     self.afi = afi
     self.safi = safi
예제 #47
0
	def exit (self, tokeniser):
		if Capability.CODE(Capability.CODE.MULTIPROTOCOL) not in self.content:
			self.content[Capability.CODE(Capability.CODE.MULTIPROTOCOL)] = MultiProtocol(NLRI.known_families())