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