Exemplo n.º 1
0
def as_path(tokeniser):
    as_seq = []
    as_set = []
    value = tokeniser()
    inset = False
    try:
        if value == "[":
            while True:
                value = tokeniser()
                if value == ",":
                    continue
                if value in ("(", "["):
                    inset = True
                    while True:
                        value = tokeniser()
                        if value == ")":
                            break
                        as_set.append(ASN.from_string(value))
                if value == ")":
                    inset = False
                    continue
                if value == "]":
                    if inset:
                        inset = False
                        continue
                    break
                as_seq.append(ASN.from_string(value))
        else:
            as_seq.append(ASN.from_string(value))
    except ValueError:
        raise ValueError("could not parse as-path")
    return ASPath(as_seq, as_set)
Exemplo n.º 2
0
def as_path (tokeniser):
	as_seq = []
	as_set = []
	value = tokeniser()
	inset = False
	try:
		if value == '[':
			while True:
				value = tokeniser()
				if value == ',':
					continue
				if value in ('(','['):
					inset = True
					while True:
						value = tokeniser()
						if value == ')':
							break
						as_set.append(ASN.from_string(value))
				if value == ')':
					inset = False
					continue
				if value == ']':
					if inset:
						inset = False
						continue
					break
				as_seq.append(ASN.from_string(value))
		else:
			as_seq.append(ASN.from_string(value))
	except ValueError:
		raise ValueError('could not parse as-path')
	return ASPath(as_seq,as_set)
Exemplo n.º 3
0
def as_path(tokeniser):
    as_seq = []
    as_set = []
    value = tokeniser()
    inset = False
    try:
        if value == '[':
            while True:
                value = tokeniser()
                if value == ',':
                    continue
                if value in ('(', '['):
                    inset = True
                    while True:
                        value = tokeniser()
                        if value in (')', ']'):
                            break
                        as_set.append(ASN.from_string(value))
                if value == ')':
                    inset = False
                    continue
                if value == ']':
                    if inset:
                        inset = False
                        continue
                    break
                as_seq.append(ASN.from_string(value))
        else:
            as_seq.append(ASN.from_string(value))
    except ValueError:
        raise ValueError('could not parse as-path')
    return ASPath(as_seq, as_set)
Exemplo n.º 4
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
Exemplo n.º 5
0
def as_path(tokeniser):
    as_path = []
    insert = None

    while True:
        value = tokeniser()

        if value == '[':
            value = tokeniser.peek()

            if value != '{':
                insert = SEQUENCE()
            else:
                insert = CONFED_SEQUENCE()

        elif value == '(':
            value = tokeniser.peek()

            if value != '{':
                insert = SET()
            else:
                insert = CONFED_SET()

        elif len(as_path) == 0:
            try:
                return ASPath(ASN.from_string(value))
            except ValueError:
                raise ValueError('could not parse as-path')
        else:
            raise ValueError('could not parse as-path')

        while True:
            value = tokeniser()

            # could be too nice eating a trailing and ignore a erroneous },,
            # but simpler that way
            if value in (',', '}'):
                continue

            if value in (')', ']'):
                as_path.append(insert)

                value = tokeniser.peek()
                if value in ('[', '('):
                    break

                return ASPath(as_path)

            try:
                insert.append(ASN.from_string(value))
                continue
            except ValueError:
                raise ValueError('could not parse as-path')
Exemplo n.º 6
0
def aggregator(tokeniser):
    eat = True if tokeniser.tokens[0] == '(' else False

    if eat:
        tokeniser()

    value = tokeniser()
    if value != '(':
        tokeniser.rewind(value)
        return None

    try:
        as_number, address = tokeniser().split(':')
        local_as = ASN.from_string(as_number)
        local_address = RouterID(address)
    except (ValueError, IndexError):
        raise ValueError('invalid aggregator')

    if eat:
        value = tokeniser()
        if value != ')':
            raise ValueError('invalid aggregator')

    # XXX: This is buggy it can be an Aggregator4
    return Aggregator(local_as, local_address)
Exemplo n.º 7
0
def aggregator(tokeniser):
    agg = tokeniser()
    eat = True if agg == '(' else False

    if eat:
        agg = tokeniser()
        if agg.endswith(')'):
            eat = False
            agg = agg[:-1]
    elif agg.startswith('('):
        if agg.endswith(')'):
            eat = False
            agg = agg[1:-1]
        else:
            eat = True
            agg = agg[1:]

    try:
        as_number, address = agg.split(':')
        local_as = ASN.from_string(as_number)
        local_address = RouterID(address)
    except (ValueError, IndexError):
        raise ValueError('invalid aggregator')

    if eat:
        if tokeniser() != ')':
            raise ValueError('invalid aggregator')

    return Aggregator(local_as, local_address)
Exemplo n.º 8
0
def aggregator(tokeniser):
    eat = True if tokeniser.tokens[0] == "(" else False

    if eat:
        tokeniser()

    value = tokeniser()
    if value != "(":
        tokeniser.rewind(value)
        return None

    try:
        as_number, address = tokeniser().split(":")
        local_as = ASN.from_string(as_number)
        local_address = RouterID(address)
    except (ValueError, IndexError):
        raise ValueError("invalid aggregator")

    if eat:
        value = tokeniser()
        if value != ")":
            raise ValueError("invalid aggregator")

            # XXX: This is buggy it can be an Aggregator4
    return Aggregator(local_as, local_address)
Exemplo n.º 9
0
 def test_2_open(self):
     capabilities = Capabilities()
     o = Open(Version(4), ASN(65500), HoldTime(180), RouterID('127.0.0.1'), capabilities)
     self.assertEqual(o.version, 4)
     self.assertEqual(o.asn, 65500)
     self.assertEqual(o.router_id, RouterID('127.0.0.1'))
     self.assertEqual(o.hold_time, 180)
     self.assertEqual(o.capabilities, {})
Exemplo n.º 10
0
def aggregator(tokeniser):
    first = tokeniser.peek()
    eat = True if first == '(' else False

    if eat:
        tokeniser()

    try:
        as_number, address = tokeniser().split(':')
        local_as = ASN.from_string(as_number)
        local_address = RouterID(address)
    except (ValueError, IndexError):
        raise ValueError('invalid aggregator')

    if eat:
        if tokeniser() != ')':
            raise ValueError('invalid aggregator')

    return Aggregator(local_as, local_address)
Exemplo n.º 11
0
def aggregator (tokeniser):
	first = tokeniser.peek()
	eat = True if first == '(' else False

	if eat:
		tokeniser()

	try:
		as_number,address = tokeniser().split(':')
		local_as = ASN.from_string(as_number)
		local_address = RouterID(address)
	except (ValueError,IndexError):
		raise ValueError('invalid aggregator')

	if eat:
		if tokeniser() != ')':
			raise ValueError('invalid aggregator')

	return Aggregator(local_as,local_address)
Exemplo n.º 12
0
def aggregator(tokeniser):
    eat = tokeniser.tokens and tokeniser.tokens[0] == '('

    if eat:
        tokeniser()

    try:
        as_number, address = tokeniser().split(':')
        local_as = ASN.from_string(as_number)
        local_address = RouterID(address)
    except (ValueError, IndexError):
        raise ValueError('invalid aggregator')

    if eat:
        if tokeniser() != ')':
            raise ValueError('invalid aggregator')

    # XXX: This could be buggy - check it
    if local_as.asn4():
        return Aggregator4(local_as, local_address)
    return Aggregator(local_as, local_address)
Exemplo n.º 13
0
def aggregator (tokeniser):
	eat = tokeniser.tokens and tokeniser.tokens[0] == '('

	if eat:
		tokeniser()

	try:
		as_number,address = tokeniser().split(':')
		local_as = ASN.from_string(as_number)
		local_address = RouterID(address)
	except (ValueError,IndexError):
		raise ValueError('invalid aggregator')

	if eat:
		if tokeniser() != ')':
			raise ValueError('invalid aggregator')

	# XXX: This could be buggy - check it
	if local_as.asn4():
		return Aggregator4(local_as,local_address)
	return Aggregator(local_as,local_address)
Exemplo n.º 14
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
Exemplo n.º 15
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
Exemplo n.º 16
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
Exemplo n.º 17
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(Version(4), ASN(neighbor.local_as), HoldTime(180),
                  RouterID(neighbor.local_address.top()), capa)
        o2 = Open(Version(4), ASN(neighbor.peer_as), HoldTime(180),
                  RouterID(neighbor.peer_address.top()), 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 127.0.0.1')

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