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.CODE.ADD_PATH] = path capa[Capability.CODE.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,exc: logger.parser('could not parse the message','error') logger.parser(str(exc),'error') return False except Exception,exc: logger.parser('could not parse the message','error') logger.parser(str(exc),'error') return False
def setUp(self): #env.log.all = True self.negotiated = {} for asn4 in (True, False): neighbor = Neighbor() neighbor.asn4 = asn4 capa = Capabilities().new(neighbor, False) capa[Capability.ID.MULTIPROTOCOL] = neighbor.families() # path = {} # for f in known_families(): # if neighbor.add_path: # path[f] = neighbor.add_path # capa[Capability.ID.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
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 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 for _ in self.write(sent_open.message()): yield _NOP self.logger.message(self.me('>> %s' % sent_open)) yield sent_open
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, {})
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
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
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 _from_json (self, string): try: parsed = json.loads(string) except ValueError: print >> sys.stderr, 'invalid JSON message' sys.exit(1) if parsed.get('exabgp','0.0.0') != json_version: print >> sys.stderr, 'invalid json version', string sys.exit(1) content = parsed.get('type','') if not content: print >> sys.stderr, 'invalid json content', string sys.exit(1) neighbor = _FakeNeighbor( parsed['neighbor']['address']['local'], parsed['neighbor']['address']['peer'], parsed['neighbor']['asn']['local'], parsed['neighbor']['asn']['peer'], ) if content == 'state': self._state() return string direction = parsed['neighbor']['direction'] category = parsed['neighbor']['message']['category'] header = parsed['neighbor']['message']['header'] body = parsed['neighbor']['message']['body'] raw = ''.join(chr(int(body[_:_+2],16)) for _ in range(0,len(body),2)) if content == 'open': message = Open.unpack_message(raw) self._open(direction,message) return self.encoder.open(neighbor,direction,message,header,body) if content == 'keapalive': return self.encoder.keepalive(neighbor,direction,header,body) if content == 'notification': return self.encoder.notification(neighbor,direction,ord(message[0]),ord(message[1]),message[2:],header,body) if not self.negotiated: print >> sys.stderr, 'invalid message sequence, open not exchange not complete', string sys.exit(1) message = Message.unpack(category,raw,self.negotiated) if content == 'update': return self.encoder.update(neighbor, direction, message, header,body) if content == 'eor': # XXX: Should not be required return self.encoder.update(neighbor, direction, message, header,body) if content == 'refresh': return self.json.refresh(neighbor, direction, message, header,body) if content == 'operational': return self.json.refresh(neighbor, direction, message, header,body) raise RuntimeError('the programer is a monkey and forgot a JSON message type')
def check_neighbor (neighbors): from exabgp.logger import Logger 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 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,'127.0.0.2',capa,180) o2 = Open(4,neighbor.peer_as,'127.0.0.3',capa,180) negotiated = Negotiated(neighbor) negotiated.sent(o1) negotiated.received(o2) # grouped = False for message 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()
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
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)
def _from_json(self, string): try: parsed = json.loads(string) except ValueError: print >> sys.stderr, 'invalid JSON message' sys.exit(1) if parsed.get('exabgp', '0.0.0') != json_version: print >> sys.stderr, 'invalid json version', string sys.exit(1) content = parsed.get('type', '') if not content: print >> sys.stderr, 'invalid json content', string sys.exit(1) neighbor = _FakeNeighbor( parsed['neighbor']['address']['local'], parsed['neighbor']['address']['peer'], parsed['neighbor']['asn']['local'], parsed['neighbor']['asn']['peer'], ) if content == 'state': self._state() return string direction = parsed['neighbor']['direction'] category = parsed['neighbor']['message']['category'] header = parsed['neighbor']['message']['header'] body = parsed['neighbor']['message']['body'] raw = ''.join( chr(int(body[_:_ + 2], 16)) for _ in range(0, len(body), 2)) if content == 'open': message = Open.unpack_message(raw) self._open(direction, message) return self.encoder.open(neighbor, direction, message, header, body) if content == 'keapalive': return self.encoder.keepalive(neighbor, direction, header, body) if content == 'notification': return self.encoder.notification(neighbor, direction, ord(message[0]), ord(message[1]), message[2:], header, body) if not self.negotiated: print >> sys.stderr, 'invalid message sequence, open not exchange not complete', string sys.exit(1) message = Message.unpack(category, raw, self.negotiated) if content == 'update': return self.encoder.update(neighbor, direction, message, header, body) if content == 'eor': # XXX: Should not be required return self.encoder.update(neighbor, direction, message, header, body) if content == 'refresh': return self.json.refresh(neighbor, direction, message, header, body) if content == 'operational': return self.json.refresh(neighbor, direction, message, header, body) raise RuntimeError( 'the programer is a monkey and forgot a JSON message type')