Exemple #1
0
	def unpack_message (cls, data, _=None):
		version = ord(data[0])
		if version != 4:
			# Only version 4 is supported nowdays..
			raise Notify(2,1,data[0])
		asn = unpack('!H',data[1:3])[0]
		hold_time = unpack('!H',data[3:5])[0]
		numeric = unpack('!L',data[5:9])[0]
		router_id = "%d.%d.%d.%d" % (numeric >> 24,(numeric >> 16) & 0xFF,(numeric >> 8) & 0xFF,numeric & 0xFF)
		capabilities = Capabilities.unpack(data[9:])
		return cls(version,asn,router_id,capabilities,hold_time)
Exemple #2
0
	def unpack_message (cls, data, _=None):
		version = ord(data[0])
		if version != 4:
			# Only version 4 is supported nowdays..
			raise Notify(2,1,data[0])
		asn = unpack('!H',data[1:3])[0]
		hold_time = unpack('!H',data[3:5])[0]
		numeric = unpack('!L',data[5:9])[0]
		router_id = "%d.%d.%d.%d" % (numeric >> 24,(numeric >> 16) & 0xFF,(numeric >> 8) & 0xFF,numeric & 0xFF)
		return cls(
			Version(version),
			ASN(asn),
			HoldTime(hold_time),
			RouterID(router_id),
			Capabilities.unpack(data[9:])
		)
Exemple #3
0
    def new_open(self):
        if self.neighbor['local-as']:
            local_as = self.neighbor['local-as']
        elif self.negotiated.received_open:
            local_as = self.negotiated.received_open.asn
        else:
            raise RuntimeError('no ASN available for the OPEN message')

        sent_open = Open(
            Version(4),
            local_as,
            self.neighbor['hold-time'],
            self.neighbor['router-id'],
            Capabilities().new(self.neighbor, self.peer._restarted),
        )

        # we do not buffer open message in purpose
        for _ in self.write(sent_open):
            yield _NOP

        log.debug('>> %s' % sent_open, self.connection.session())
        yield sent_open
Exemple #4
0
    def new_open(self, restarted):
        sent_open = Open(4, self.neighbor.local_as, self.neighbor.router_id.ip,
                         Capabilities().new(self.neighbor, restarted),
                         self.neighbor.hold_time)

        # we do not buffer open message in purpose
        msg_send = sent_open.message()
        for _ in self.write(msg_send):
            yield _NOP

        self.logger.message(self.me('>> %s' % sent_open))
        if self.neighbor.api[Message.ID.OPEN]:
            if self.neighbor.api['consolidate']:
                header = msg_send[0:38]
                body = msg_send[38:]
                self.peer.reactor.processes.message(Message.ID.OPEN, self.peer,
                                                    sent_open, header, body,
                                                    'sent')
            else:
                self.peer.reactor.processes.message(Message.ID.OPEN, self.peer,
                                                    sent_open, '', '', 'sent')
        yield sent_open
Exemple #5
0
	def setUp (self):
		self.negotiated = {}

		for asn4 in (True,False):
			neighbor = FakeNeighbor()
			neighbor.asn4 = asn4

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

			# path = {}
			# for f in NLRI.known_families():
			# 	if neighbor.add_path:
			# 		path[f] = neighbor.add_path
			# capa[Capability.CODE.ADD_PATH] = path

			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)

			self.negotiated[asn4] = negotiated
Exemple #6
0
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
Exemple #7
0
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
Exemple #8
0
def check_neighbor(neighbor):
    from exabgp.logger import Logger

    logger = Logger()
    logger._parser = True
    logger.parser('\ndecoding routes in configuration')

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

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

    capa = Capabilities().new(n, False)
    capa[Capability.ID.ADD_PATH] = path
    capa[Capability.ID.MULTIPROTOCOL] = n.families()

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

    for nei in neighbor.keys():
        for message in neighbor[nei].rib.outgoing.updates(False):
            pass

        for change1 in neighbor[nei].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))

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

                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('----------------------------------------')

            except Notify, e:
                logger.parser('----------------------------------------')
                logger.parser(str(e))
                logger.parser('----------------------------------------')
                return False
Exemple #9
0
def check_update(neighbor, raw):
    from exabgp.logger import Logger

    logger = Logger()
    logger._parser = True
    logger.parser('\ndecoding routes in configuration')

    n = neighbor[neighbor.keys()[0]]
    p = Peer(n, None)

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

    capa = Capabilities().new(n, False)
    capa[Capability.ID.ADD_PATH] = path
    capa[Capability.ID.MULTIPROTOCOL] = n.families()

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

    o1 = Open(4, n.local_as, routerid_1, capa, 180)
    o2 = Open(4, n.peer_as, routerid_2, capa, 180)
    negotiated = Negotiated(n)
    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, e:
            logger.parser('could not parse the message')
            logger.parser(str(e))
            return False
        except Exception, e:
            logger.parser('could not parse the message')
            logger.parser(str(e))
            return False
Exemple #10
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()
Exemple #11
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
Exemple #12
0
 def unpack_message(cls, data, _=None):
     version = data[0]
     if version != 4:
         # Only version 4 is supported nowdays..
         raise Notify(2, 1, bytes(data[0], 'ascii'))
     asn = unpack('!H', data[1:3])[0]
     hold_time = unpack('!H', data[3:5])[0]
     numeric = unpack('!L', data[5:9])[0]
     router_id = "%d.%d.%d.%d" % (numeric >> 24, (numeric >> 16) & 0xFF, (numeric >> 8) & 0xFF, numeric & 0xFF)
     return cls(Version(version), ASN(asn), HoldTime(hold_time), RouterID(router_id), Capabilities.unpack(data[9:]))