Example #1
0
    def unpack_message(cls, data, negotiated):  # pylint: disable=W0613
        what = Type(unpack('!H', data[0:2])[0])
        length = unpack('!H', data[2:4])[0]

        decode, klass = cls.registered_operational.get(what, ('unknown', None))

        if decode == 'advisory':
            afi = unpack('!H', data[4:6])[0]
            safi = ordinal(data[6])
            data = data[7:length + 4]
            return klass(afi, safi, data)
        elif decode == 'query':
            afi = unpack('!H', data[4:6])[0]
            safi = ordinal(data[6])
            routerid = RouterID.unpack(data[7:11])
            sequence = unpack('!L', data[11:15])[0]
            return klass(afi, safi, routerid, sequence)
        elif decode == 'counter':
            afi = unpack('!H', data[4:6])[0]
            safi = ordinal(data[6])
            routerid = RouterID.unpack(data[7:11])
            sequence = unpack('!L', data[11:15])[0]
            counter = unpack('!L', data[15:19])[0]
            return klass(afi, safi, routerid, sequence, counter)
        else:
            print('ignoring ATM this kind of message')
Example #2
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

            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)

            self.negotiated[asn4] = negotiated
Example #3
0
	def unpack_message (cls, data, negotiated):  # pylint: disable=W0613
		what = Type(unpack('!H',data[0:2])[0])
		length = unpack('!H',data[2:4])[0]

		decode,klass = cls.registered_operational.get(what,('unknown',None))

		if decode == 'advisory':
			afi = unpack('!H',data[4:6])[0]
			safi = ordinal(data[6])
			data = data[7:length+4]
			return klass(afi,safi,data)
		elif decode == 'query':
			afi = unpack('!H',data[4:6])[0]
			safi = ordinal(data[6])
			routerid = RouterID.unpack(data[7:11])
			sequence = unpack('!L',data[11:15])[0]
			return klass(afi,safi,routerid,sequence)
		elif decode == 'counter':
			afi = unpack('!H',data[4:6])[0]
			safi = ordinal(data[6])
			routerid = RouterID.unpack(data[7:11])
			sequence = unpack('!L',data[11:15])[0]
			counter = unpack('!L',data[15:19])[0]
			return klass(afi,safi,routerid,sequence,counter)
		else:
			print('ignoring ATM this kind of message')
Example #4
0
def OperationalFactory (data):
	what = Type(unpack('!H',data[0:2])[0])
	length = unpack('!H',data[2:4])[0]

	if what == OperationalType.ADM:
		afi = unpack('!H',data[4:6])[0]
		safi = ord(data[6])
		data = data[7:length+4]
		return Advisory.ADM(afi,safi,data)
	elif what == OperationalType.ASM:
		afi = unpack('!H',data[4:6])[0]
		safi = ord(data[6])
		data = data[7:length+4]
		return Advisory.ASM(afi,safi,data)
	elif what == OperationalType.RPCQ:
		afi = unpack('!H',data[4:6])[0]
		safi = ord(data[6])
		routerid = RouterID(unpack('!H',data[7:9])[0])
		sequence = unpack('!H',data[9:11])[0]
		return State.RPCQ(afi,safi,routerid,sequence)
	elif what == OperationalType.RPCP:
		afi = unpack('!H',data[4:6])[0]
		safi = ord(data[6])
		routerid = RouterID(unpack('!H',data[7:9])[0])
		sequence = unpack('!H',data[9:11])[0]
		count = unpack('!H',data[11:15])[0]
		return State.RPCQ(afi,safi,routerid,sequence,count)
	else:
		print 'ignoring ATM this kind of message'
Example #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(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)

            self.negotiated[asn4] = negotiated
Example #6
0
def OperationalFactory(data):
    what = Type(unpack('!H', data[0:2])[0])
    length = unpack('!H', data[2:4])[0]

    decode, klass = OperationalGroup.get(what, ('unknown', None))

    if decode == 'advisory':
        afi = unpack('!H', data[4:6])[0]
        safi = ord(data[6])
        data = data[7:length + 4]
        return klass(afi, safi, data)
    elif decode == 'query':
        afi = unpack('!H', data[4:6])[0]
        safi = ord(data[6])
        routerid = RouterID('.'.join(str(ord(_)) for _ in data[7:11]))
        sequence = unpack('!L', data[11:15])[0]
        return klass(afi, safi, routerid, sequence)
    elif decode == 'counter':
        afi = unpack('!H', data[4:6])[0]
        safi = ord(data[6])
        routerid = RouterID('.'.join(str(ord(_)) for _ in data[7:11]))
        sequence = unpack('!L', data[11:15])[0]
        counter = unpack('!L', data[15:19])[0]
        return klass(afi, safi, routerid, sequence, counter)
    elif decode == 'interface':
        afi = unpack('!H', data[4:6])[0]
        safi = ord(data[6])
        routerid = RouterID('.'.join(str(ord(_)) for _ in data[7:11]))
        sequence = unpack('!L', data[11:15])[0]
        rxc = unpack('!L', data[15:19])[0]
        txc = unpack('!L', data[19:23])[0]
        return klass(afi, safi, routerid, sequence, rxc, txc)
    else:
        print 'ignoring ATM this kind of message'
Example #7
0
	def __init__ (self,what,afi,safi,routerid,sequence=None,data=''):
		self.routerid = routerid
		self.routerid = RouterID(routerid)
		self.sequence = self._sequence() if sequence is None else sequence
		OperationalFamily.__init__(
			self,what,
			afi,safi,
			'%s%s%s' % (self.routerid.pack(),pack('!H',self.sequence),data)
		)
Example #8
0
class Open(Message):
    ID = Message.CODE.OPEN
    TYPE = chr(Message.CODE.OPEN)

    def __init__(self, version, asn, router_id, capabilities, hold_time):
        self.version = Version(version)
        self.asn = ASN(asn)
        self.hold_time = HoldTime(hold_time)
        self.router_id = RouterID(router_id)
        self.capabilities = capabilities

    def message(self, negotiated=None):
        return self._message(
            "%s%s%s%s%s" %
            (self.version.pack(), self.asn.trans(), self.hold_time.pack(),
             self.router_id.pack(), self.capabilities.pack()))

    def __str__(self):
        return "OPEN version=%d asn=%d hold_time=%s router_id=%s capabilities=[%s]" % (
            self.version, self.asn, self.hold_time, self.router_id,
            self.capabilities)

    @classmethod
    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)
Example #9
0
class Open (Message):
	ID = Message.CODE.OPEN
	TYPE = chr(Message.CODE.OPEN)

	def __init__ (self, version, asn, router_id, capabilities, hold_time):
		self.version = Version(version)
		self.asn = ASN(asn)
		self.hold_time = HoldTime(hold_time)
		self.router_id = RouterID(router_id)
		self.capabilities = capabilities

	def message (self):
		return self._message("%s%s%s%s%s" % (
			self.version.pack(),
			self.asn.trans(),
			self.hold_time.pack(),
			self.router_id.pack(),
			self.capabilities.pack()
		))

	def __str__ (self):
		return "OPEN version=%d asn=%d hold_time=%s router_id=%s capabilities=[%s]" % (self.version, self.asn, self.hold_time, self.router_id,self.capabilities)

	@classmethod
	def unpack_message (cls, data, _):
		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)
Example #10
0
	def validate (self, neighbor):
		if self.peer_as != neighbor.peer_as:
			return (2,2,'ASN in OPEN (%d) did not match ASN expected (%d)' % (self.received_open.asn,neighbor.peer_as))

		# RFC 6286 : https://tools.ietf.org/html/rfc6286
		# XXX: FIXME: check that router id is not self
		if self.received_open.router_id == RouterID('0.0.0.0'):
			return (2,3,'0.0.0.0 is an invalid router_id')

		if self.received_open.asn == neighbor.local_as:
			# router-id must be unique within an ASN
			if self.received_open.router_id == neighbor.router_id:
				return (2,3,'BGP Identifier collision, same router-id (%s) on both sides of this IBGP session' % self.received_open.router_id)

		if self.received_open.hold_time and self.received_open.hold_time < 3:
			return (2,6,'Hold Time is invalid (%d)' % self.received_open.hold_time)

		if self.multisession not in (True,False):
			# XXX: FIXME: should we not use a string and perform a split like we do elswhere ?
			# XXX: FIXME: or should we use this trick in the other case ?
			return self.multisession

		s = set(self.sent_open.capabilities.get(Capability.CODE.MULTIPROTOCOL,[]))
		r = set(self.received_open.capabilities.get(Capability.CODE.MULTIPROTOCOL,[]))
		mismatch = s ^ r

		for family in mismatch:
			self.mismatch.append(('exabgp' if family in r else 'peer',family))

		return None
Example #11
0
    def aggregator(self, scope, name, command, tokens):
        try:
            if tokens:
                if tokens.pop(0) != '(':
                    raise ValueError('invalid aggregator syntax')
                asn, address = tokens.pop(0).split(':')
                if tokens.pop(0) != ')':
                    raise ValueError('invalid aggregator syntax')
                local_as = ASN(asn)
                local_address = RouterID(address)
            else:
                local_as = scope[-1]['local-as']
                local_address = scope[-1]['local-address']
        except (ValueError, IndexError):
            return self.error.set(self.syntax)
        except KeyError:
            return self.error(
                'local-as and/or local-address missing from neighbor/group to make aggregator'
            )
        except ValueError:
            return self.error.set(self.syntax)

        scope[-1]['announce'][-1].attributes.add(
            Aggregator(local_as, local_address))
        return True
Example #12
0
	def validate (self,neighbor):
		if not self.asn4:
			if neighbor.local_as.asn4():
				return (2,0,'peer does not speak ASN4, we are stuck')
			else:
				# we will use RFC 4893 to convey new ASN to the peer
				# XXX: FIXME
				pass

		if self.peer_as != neighbor.peer_as:
			return (2,2,'ASN in OPEN (%d) did not match ASN expected (%d)' % (self.received_open.asn,neighbor.peer_as))

		# RFC 6286 : http://tools.ietf.org/html/rfc6286
		# XXX: FIXME: check that router id is not self
		if self.received_open.router_id == RouterID('0.0.0.0'):
			return (2,3,'0.0.0.0 is an invalid router_id')

		if self.received_open.asn == neighbor.local_as:
			# router-id must be unique within an ASN
			if self.received_open.router_id == neighbor.router_id:
				return (2,3,'BGP Indendifier collision, same router-id (%s) on both side of this IBGP session' % self.received_open.router_id)

		if self.received_open.hold_time and self.received_open.hold_time < 3:
			return (2,6,'Hold Time is invalid (%d)' % self.received_open.hold_time)

		if self.multisession not in (True,False):
			# XXX: FIXME: should we not use a string and perform a split like we do elswhere ?
			# XXX: FIXME: or should we use this trick in the other case ?
			return self.multisession

		return None
Example #13
0
 def __init__(self):
     self.update({
         'description': 'a test neighbor',
         'router-id': RouterID('127.0.0.1'),
         'local-address': IPv4('127.0.0.1'),
         'peer-address': IPv4('127.0.0.1'),
         'host-name': 'localhost',
         'domain-name': 'localdomain',
         'peer-as': ASN('65500'),
         'local-as': ASN('65500'),
         'hold-time': HoldTime(180),
         'capability': {
             'asn4': False,
             'add-path': 0,
             'extended_message': False,
             'nexthop': None,
             'route-refresh': False,
             'graceful-restart': False,
             'multi-session': None,
             'add-path': None,
             'aigp': None,
             'operational': None,
             'extended-message': True,
         },
     })
Example #14
0
class FakeNeighbor(object):
    description = 'a test neighbor'
    router_id = RouterID('127.0.0.1')
    local_address = IPv4('127.0.0.1')
    peer_address = IPv4('127.0.0.1')
    host_name = 'localhost'
    domain_name = 'localdomain'
    peer_as = ASN('65500')
    local_as = ASN('65500')
    hold_time = HoldTime(180)
    asn4 = False
    add_path = 0
    extended_message = False
    nexthop = None

    # capability
    route_refresh = False
    graceful_restart = False
    multisession = None
    add_path = None
    aigp = None
    operational = None

    @staticmethod
    def families():
        return NLRI.known_families()
Example #15
0
def _operational(klass, parameters, tokeniser):
    def utf8(string):
        return string.encode('utf-8')

    def valid(_):
        return True

    def u32(_):
        return int(_) <= 0xFFFFFFFF

    def u64(_):
        return int(_) <= 0xFFFFFFFFFFFFFFFF

    def advisory(_):
        return len(_.encode('utf-8')) <= MAX_ADVISORY + 2  # the two quotes

    convert = {'afi': AFI.value, 'safi': SAFI.value, 'sequence': int, 'counter': int, 'advisory': utf8}

    validate = {
        'afi': AFI.value,
        'safi': SAFI.value,
        'sequence': u32,
        'counter': u64,
    }

    number = len(parameters) * 2
    tokens = []
    while len(tokens) != number:
        tokens.append(tokeniser())

    data = {}

    while tokens and parameters:
        command = tokens.pop(0).lower()
        value = tokens.pop(0)

        if command == 'router-id':
            if isipv4(value):
                data['routerid'] = RouterID(value)
            else:
                raise ValueError('invalid operational value for %s' % command)
            continue

        expected = parameters.pop(0)

        if command != expected:
            raise ValueError('invalid operational syntax, unknown argument %s' % command)
        if not validate.get(command, valid)(value):
            raise ValueError('invalid operational value for %s' % command)

        data[command] = convert[command](value)

    if tokens or parameters:
        raise ValueError('invalid advisory syntax, missing argument(s) %s' % ', '.join(parameters))

    if 'routerid' not in data:
        data['routerid'] = None

    return klass(**data)
Example #16
0
 def test_2_open(self):
     capabilities = Capabilities()
     o = Open(4, 65500, '127.0.0.1', capabilities, 180)
     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, {})
Example #17
0
    def router_id(self, scope, name, command, tokens):
        try:
            ip = RouterID(tokens[0])
        except (IndexError, ValueError):
            return self.error.set('"%s" is an invalid IP address' %
                                  ' '.join(tokens))

        scope[-1][command] = ip
        return True
Example #18
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:]))
Example #19
0
class SequencedOperationalFamily (OperationalFamily):
	__sequence_number = 0

	def _sequence (self):
		self.__sequence_number +=1
		return self.__sequence_number

	def __init__ (self,what,afi,safi,routerid,sequence=None,data=''):
		self.routerid = routerid
		self.routerid = RouterID(routerid)
		self.sequence = self._sequence() if sequence is None else sequence
		OperationalFamily.__init__(
			self,what,
			afi,safi,
			'%s%s%s' % (self.routerid.pack(),pack('!H',self.sequence),data)
		)
Example #20
0
def aggregator(tokeniser):
    value = tokeniser()
    if value != '(':
        tokeniser.rewind(value)
        return None

    try:
        as_number, address = tokeniser().split(':')
    except (ValueError, IndexError):
        raise ValueError('invalid aggregator')

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

    local_as = ASN(as_number)
    local_address = RouterID(address)

    # XXX: This is buggy it can be an Aggregator4
    return Aggregator(local_as, local_address)
Example #21
0
class Neighbor:
    description = 'a test neighbor'
    router_id = RouterID('127.0.0.1')
    local_address = IPv4('127.0.0.1')
    peer_address = IPv4('127.0.0.1')
    peer_as = ASN('65500')
    local_as = ASN('65500')
    hold_time = HoldTime(180)
    asn4 = False
    add_path = 0

    # capability
    route_refresh = False
    graceful_restart = False
    multisession = None
    add_path = None
    aigp = None

    @staticmethod
    def families():
        return known_families()
Example #22
0
class Open (Message):
	TYPE = chr(Message.Type.OPEN)

	def __init__ (self,version,asn,router_id,capabilities,hold_time):
		self.version = Version(version)
		self.asn = ASN(asn)
		self.hold_time = HoldTime(hold_time)
		self.router_id = RouterID(router_id)
		self.capabilities = capabilities

	def message (self):
		return self._message("%s%s%s%s%s" % (
			self.version.pack(),
			self.asn.trans(),
			self.hold_time.pack(),
			self.router_id.pack(),
			self.capabilities.pack()
		))

	def __str__ (self):
		return "OPEN version=%d asn=%d hold_time=%s router_id=%s capabilities=[%s]" % (self.version, self.asn, self.hold_time, self.router_id,self.capabilities)
Example #23
0
        message_id = 1
        body = ''.join([
            chr(c) for c in [
                0x4, 0xff, 0xfe, 0x0, 0xb4, 0x0, 0x0, 0x0, 0x0, 0x20, 0x2, 0x6,
                0x1, 0x4, 0x0, 0x1, 0x0, 0x1, 0x2, 0x6, 0x1, 0x4, 0x0, 0x2,
                0x0, 0x1, 0x2, 0x2, 0x80, 0x0, 0x2, 0x2, 0x2, 0x0, 0x2, 0x6,
                0x41, 0x4, 0x0, 0x0, 0xff, 0xfe
            ]
        ])
        negotiated = {'invalid': 'test'}

        o = Message.unpack(message_id, body, negotiated)

        self.assertEqual(o.version, 4)
        self.assertEqual(o.asn, 65534)
        self.assertEqual(o.router_id, RouterID('0.0.0.0'))
        self.assertEqual(o.hold_time, 180)
        for k, v in o.capabilities.items():
            self.assertEqual(v, check_capa[k])

    def test_2_open(self):
        capabilities = Capabilities()
        o = Open(4, 65500, '127.0.0.1', capabilities, 180)
        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, {})


if __name__ == '__main__':
Example #24
0
	def __init__ (self, version, asn, router_id, capabilities, hold_time):
		self.version = Version(version)
		self.asn = ASN(asn)
		self.hold_time = HoldTime(hold_time)
		self.router_id = RouterID(router_id)
		self.capabilities = capabilities
Example #25
0
    def new_connections(self):
        if not self.serving:
            return
        yield None

        reactor = self._reactor
        ranged_neighbor = []

        for connection in self._connected():
            self.logger.debug('new connection received %s' % connection.name(),
                              'network')
            for key in reactor.peers:
                peer = reactor.peers[key]
                neighbor = peer.neighbor

                connection_local = IP.create(connection.local).address()
                neighbor_peer_start = neighbor.peer_address.address()
                neighbor_peer_next = neighbor_peer_start + neighbor.range_size

                if not neighbor_peer_start <= connection_local < neighbor_peer_next:
                    continue

                connection_peer = IP.create(connection.peer).address()
                neighbor_local = neighbor.local_address.address()

                if connection_peer != neighbor_local:
                    if not neighbor.auto_discovery:
                        continue

                # we found a range matching for this connection
                # but the peer may already have connected, so
                # we need to iterate all individual peers before
                # handling "range" peers
                if neighbor.range_size > 1:
                    ranged_neighbor.append(peer.neighbor)
                    continue

                denied = peer.handle_connection(connection)
                if denied:
                    self.logger.debug(
                        'refused connection from %s due to the state machine' %
                        connection.name(), 'network')
                    break
                self.logger.debug(
                    'accepted connection from %s' % connection.name(),
                    'network')
                break
            else:
                # we did not break (and nothign was found/done or we have group match)
                matched = len(ranged_neighbor)
                if matched > 1:
                    self.logger.debug(
                        'could not accept connection from %s (more than one neighbor match)'
                        % connection.name(), 'network')
                    reactor.asynchronous.schedule(
                        str(uuid.uuid1()), 'sending notification (6,5)',
                        connection.notification(
                            6, 5,
                            'could not accept the connection (more than one neighbor match)'
                        ))
                    return
                if not matched:
                    self.logger.debug(
                        'no session configured for %s' % connection.name(),
                        'network')
                    reactor.asynchronous.schedule(
                        str(uuid.uuid1()), 'sending notification (6,3)',
                        connection.notification(
                            6, 3, 'no session configured for the peer'))
                    return

                new_neighbor = copy.copy(ranged_neighbor[0])
                new_neighbor.range_size = 1
                new_neighbor.generated = True
                new_neighbor.local_address = IP.create(connection.peer)
                new_neighbor.peer_address = IP.create(connection.local)
                if not new_neighbor.router_id:
                    new_neighbor.router_id = RouterID.create(connection.local)

                new_peer = Peer(new_neighbor, reactor)
                denied = new_peer.handle_connection(connection)
                if denied:
                    self.logger.debug(
                        'refused connection from %s due to the state machine' %
                        connection.name(), 'network')
                    return

                reactor.peers[new_neighbor.name()] = new_peer
                return
Example #26
0
def routerid(tokeniser):
    return RouterID(tokeniser())
Example #27
0
	def new_connections (self):
		if not self.serving:
			return
		yield None

		reactor = self._reactor
		ranged_neighbor = []

		for connection in self._connected():
			self.logger.debug('new connection received %s' % connection.name(),'network')
			for key in reactor.peers:
				peer = reactor.peers[key]
				neighbor = peer.neighbor

				connection_local = IP.create(connection.local).address()
				neighbor_peer_start = neighbor.peer_address.address()
				neighbor_peer_next = neighbor_peer_start + neighbor.range_size

				if not neighbor_peer_start <= connection_local < neighbor_peer_next:
					continue

				connection_peer = IP.create(connection.peer).address()
				neighbor_local = neighbor.local_address.address()

				if connection_peer != neighbor_local:
					if not neighbor.auto_discovery:
						continue

				# we found a range matching for this connection
				# but the peer may already have connected, so
				# we need to iterate all individual peers before
				# handling "range" peers
				if neighbor.range_size > 1:
					ranged_neighbor.append(peer.neighbor)
					continue

				denied = peer.handle_connection(connection)
				if denied:
					self.logger.debug('refused connection from %s due to the state machine' % connection.name(),'network')
					break
				self.logger.debug('accepted connection from %s' % connection.name(),'network')
				break
			else:
				# we did not break (and nothign was found/done or we have group match)
				matched = len(ranged_neighbor)
				if matched > 1:
					self.logger.debug('could not accept connection from %s (more than one neighbor match)' % connection.name(),'network')
					reactor.asynchronous.schedule(str(uuid.uuid1()), 'sending notification (6,5)', connection.notification(
						6, 5, 'could not accept the connection (more than one neighbor match)'))
					return
				if not matched:
					self.logger.debug('no session configured for %s' % connection.name(),'network')
					reactor.asynchronous.schedule(str(uuid.uuid1()), 'sending notification (6,3)', connection.notification(
						6, 3, 'no session configured for the peer'))
					return

				new_neighbor = copy.copy(ranged_neighbor[0])
				new_neighbor.range_size = 1
				new_neighbor.generated = True
				new_neighbor.local_address = IP.create(connection.peer)
				new_neighbor.peer_address = IP.create(connection.local)
				new_neighbor.router_id = RouterID.create(connection.local)

				new_peer = Peer(new_neighbor,self)
				denied = new_peer.handle_connection(connection)
				if denied:
					self.logger.debug('refused connection from %s due to the state machine' % connection.name(),'network')
					return

				reactor.peers[new_neighbor.name()] = new_peer
				return
Example #28
0
    def _operational(self, klass, parameters, tokens):
        def utf8(string):
            return string.encode('utf-8')[1:-1]

        convert = {
            'afi': AFI.value,
            'safi': SAFI.value,
            'sequence': int,
            'counter': long,
            'advisory': utf8
        }

        def valid(_):
            return True

        def u32(_):
            return int(_) <= 0xFFFFFFFF

        def u64(_):
            return long(_) <= 0xFFFFFFFFFFFFFFFF

        def advisory(_):
            return len(_.encode('utf-8')) <= MAX_ADVISORY + 2  # the two quotes

        validate = {
            'afi': AFI.value,
            'safi': SAFI.value,
            'sequence': u32,
            'counter': u64,
        }

        number = len(parameters) * 2
        tokens = formated(tokens).split(' ', number - 1)
        if len(tokens) != number:
            return self.error.set(
                'invalid operational syntax, wrong number of arguments')

        data = {}

        while tokens and parameters:
            command = tokens.pop(0).lower()
            value = tokens.pop(0)

            if command == 'router-id':
                if isipv4(value):
                    data['routerid'] = RouterID(value)
                else:
                    self.error.set('invalid operational value for %s' %
                                   command)
                    return None
                continue

            expected = parameters.pop(0)

            if command != expected:
                self.error.set(
                    'invalid operational syntax, unknown argument %s' %
                    command)
                return None
            if not validate.get(command, valid)(value):
                self.error.set('invalid operational value for %s' % command)
                return None

            data[command] = convert[command](value)

        if tokens or parameters:
            self.error.set('invalid advisory syntax, missing argument(s) %s' %
                           ', '.join(parameters))
            return None

        if 'routerid' not in data:
            data['routerid'] = None

        return klass(**data)
Example #29
0
def router_id(tokeniser):
    value = tokeniser()
    try:
        return RouterID(value)
    except ValueError:
        raise ValueError('"%s" is an invalid router-id' % value)
Example #30
0
 def __init__(self, version, asn, router_id, capabilities, hold_time):
     self.version = Version(version)
     self.asn = ASN(asn)
     self.hold_time = HoldTime(hold_time)
     self.router_id = RouterID(router_id)
     self.capabilities = capabilities