Exemple #1
0
    def _connect(self):
        proto = Protocol(self)
        generator = proto.connect()

        connected = False
        try:
            for connected in generator:
                if connected:
                    break
                if self._teardown:
                    raise Stop()
                # we want to come back as soon as possible
                yield ACTION.LATER
            self.proto = proto
        except Stop:
            # Connection failed
            if not connected and self.proto:
                self.proto.close(
                    'connection to %s:%d failed' %
                    (self.neighbor.peer_address, self.neighbor.connect))

            # A connection arrived before we could establish !
            if not connected or self.proto:
                yield ACTION.NOW
                raise Interrupted()
Exemple #2
0
	def handle_connection (self, connection):
		# if the other side fails, we go back to idle
		if self.fsm == FSM.ESTABLISHED:
			self.logger.debug('we already have a peer in state established for %s' % connection.name(),self.id())
			return connection.notification(6,7,b'could not accept the connection, already established')

		# 6.8 The convention is to compare the BGP Identifiers of the peers
		# involved in the collision and to retain only the connection initiated
		# by the BGP speaker with the higher-valued BGP Identifier.
		# FSM.IDLE , FSM.ACTIVE , FSM.CONNECT , FSM.OPENSENT , FSM.OPENCONFIRM , FSM.ESTABLISHED

		if self.fsm == FSM.OPENCONFIRM:
			# We cheat: we are not really reading the OPEN, we use the data we have instead
			# it does not matter as the open message will be the same anyway
			local_id = self.neighbor.router_id.pack()
			remote_id = self.proto.negotiated.received_open.router_id.pack()

			if remote_id < local_id:
				self.logger.debug('closing incoming connection as we have an outgoing connection with higher router-id for %s' % connection.name(),self.id())
				return connection.notification(6,7,b'could not accept the connection, as another connection is already in open-confirm and will go through')

		# accept the connection
		if self.proto:
			self.proto.close('closing outgoing connection as we have another incoming on with higher router-id')
		self.proto = Protocol(self).accept(connection)
		self.generator = None
		# Let's make sure we do some work with this connection
		self._delay.reset()
		return None
Exemple #3
0
	def test_2_selfparse_KeepAlive (self):
		ds = KeepAlive()

		txt = ds.message()
		network = Network(txt)
		bgp = Protocol(self.neighbor,network)

		message = bgp.read_message()
		self.assertEqual(message.TYPE,KeepAlive.TYPE)
Exemple #4
0
	def incoming (self, connection):
		# if the other side fails, we go back to idle
		if self._['in']['proto'] not in (True,False,None):
			self.logger.network('we already have a peer at this address')
			return False

		self._['in']['proto'] = Protocol(self).accept(connection)
		# Let's make sure we do some work with this connection
		self._['in']['generator'] = None
		self._['in']['state'] = STATE.CONNECT
		return True
Exemple #5
0
    def incoming(self, connection):
        # if the other side fails, we go back to idle
        if self._incoming.proto not in (True, False, None):
            self.logger.network('we already have a peer at this address')
            return False

        # self._incoming.fsm.change(FSM.ACTIVE)
        self._incoming.proto = Protocol(self).accept(connection)
        # Let's make sure we do some work with this connection
        self._incoming.generator = None
        return True
Exemple #6
0
	def test_1_selfparse_open (self):
		ds = Open(4,65000,'1.2.3.4',Capabilities().default(),30)

		txt = ds.message()
		network = Network(txt)
		#print [hex(ord(c)) for c in txt]
		bgp = Protocol(self.neighbor,network)
		bgp.follow = False

		o = bgp.read_open('127.0.0.1')
		self.assertEqual(o.version,4)
		self.assertEqual(o.asn,65000)
		self.assertEqual(o.hold_time,30)
		self.assertEqual(str(o.router_id),'1.2.3.4')
Exemple #7
0
	def test_5_selfparse_update_announce_multi (self):
		o = Open(4,65000,'1.2.3.4',Capabilities().default(),30).message()
		k = KeepAlive().message()
		d = Delta(self.table)
		a = d.announce(65000,65000)
		self.table.update(routes[:-1])
		u = d.update(65000,65000)

		network = Network(o+k+''.join(u))
		bgp = Protocol(self.neighbor,network)
		bgp.follow = False

		self.assertEqual(bgp.read_message().TYPE,Open.TYPE)
		self.assertEqual(bgp.read_message().TYPE,KeepAlive.TYPE)
		updates = bgp.read_message()
		self.assertEqual(updates.TYPE,Update.TYPE)
		self.assertEqual(str(updates.added()[0]),'10.0.2.1/32')
Exemple #8
0
	def test_6_holdtime (self):
		class MyPeer(Network):
			_data = StringIO(Open(4,65000,'1.2.3.4',Capabilities().default(),90).message())
			def read (self,l):
				return self._data.read(l)

		network = MyPeer('')

		bgp = Protocol(self.neighbor,network)
		bgp.follow = False

		before = bgp.neighbor.hold_time
		bgp.new_open()
		bgp.read_open('127.0.0.1')
		after = bgp.neighbor.hold_time

		self.assertEqual(after,min(before,90))
Exemple #9
0
	def _connect (self):
		# try to establish the outgoing connection

		proto = Protocol(self)
		generator = proto.connect()

		connected = False
		try:
			while not connected:
				if self._teardown:
					raise StopIteration()
				connected = generator.next()
				# we want to come back as soon as possible
				yield ACTION.LATER
		except StopIteration:
			# Connection failed
			if not connected:
				proto.close('connection to peer failed',self._['in']['state'] != STATE.ESTABLISHED)
			# A connection arrived before we could establish !
			if not connected or self._['in']['proto']:
				stop = Interrupted()
				stop.direction = 'out'
				yield ACTION.NOW
				raise stop

		self._['out']['state'] = STATE.CONNECT
		self._['out']['proto'] = proto

		# send OPEN
		# Only yield if we have not the open, otherwise the reactor can run the other connection
		# which would be bad as we need to set the state without going to the other peer
		message = Message.CODE.NOP
		for message in proto.new_open(self._restarted):
			if ord(message.TYPE) == Message.CODE.NOP:
				yield ACTION.NOW

		proto.negotiated.sent(message)

		self._['out']['state'] = STATE.OPENSENT

		# Read OPEN
		wait = environment.settings().bgp.openwait
		opentimer = ReceiveTimer(self.me,wait,1,1,'waited for open too long, we do not like stuck in active')
		for message in self._['out']['proto'].read_open(self.neighbor.peer_address.ip):
			opentimer.check_ka(message)
			# XXX: FIXME: change the whole code to use the ord and not the chr version
			# Only yield if we have not the open, otherwise the reactor can run the other connection
			# which would be bad as we need to do the collission check
			if ord(message.TYPE) == Message.CODE.NOP:
				yield ACTION.LATER

		self._['out']['state'] = STATE.OPENCONFIRM
		proto.negotiated.received(message)
		proto.validate_open()

		if self._['in']['state'] == STATE.OPENCONFIRM:
			self.logger.network('outgoing connection finds the incoming connection is in openconfirm')
			local_id = self.neighbor.router_id.packed
			remote_id = proto.negotiated.received_open.router_id.packed

			if local_id < remote_id:
				self.logger.network('aborting the outgoing connection')
				stop = Interrupted()
				stop.direction = 'out'
				raise stop
			else:
				self.logger.network('closing the incoming connection')
				self._stop('in','collision local id < remote id')
				yield ACTION.LATER

		# Send KEEPALIVE
		for message in proto.new_keepalive('OPENCONFIRM'):
			yield ACTION.NOW

		# Start keeping keepalive timer
		self.recv_timer = ReceiveTimer(self.me,proto.negotiated.holdtime,4,0)
		# Read KEEPALIVE
		for message in self._['out']['proto'].read_keepalive():
			self.recv_timer.check_ka(message)
			yield ACTION.NOW

		self._['out']['state'] = STATE.ESTABLISHED
		# let the caller know that we were sucesfull
		yield ACTION.NOW
Exemple #10
0
    0x75, 0x18, 0x67, 0x5, 0x74, 0x18, 0x67, 0x3, 0x10, 0x13, 0x65, 0x37, 0xc0,
    0x11, 0x65, 0x32, 0x80, 0x18, 0x65, 0x0, 0x1f, 0x18, 0x65, 0x0, 0x1e, 0x18,
    0x65, 0x0, 0x1d, 0x18, 0x65, 0x0, 0x1c, 0xf, 0x24, 0x2, 0x11, 0x1b, 0x79,
    0x80, 0x13, 0x1b, 0x60, 0x20, 0x15, 0x1b, 0x60, 0x10, 0x10, 0x1, 0x15,
    0x16, 0x1, 0x0, 0x1c, 0x17, 0x1, 0x0, 0x1a
]

route = header + body

from StringIO import StringIO
from exabgp.reactor.protocol import Protocol
from exabgp.reactor.peer import Peer
from exabgp.bgp.neighbor import Neighbor


class Connection(StringIO):
    def pending(self, **argv):
        return True


cnx = Connection(''.join([chr(_) for _ in route]))
neibor = Neighbor()
peer = Peer(neibor, None)

#import pdb
#pdb.set_trace()

proto = Protocol(peer, cnx)
proto._asn4 = True
print proto.UpdateFactory(body)