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)
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) return cls( Version(version), ASN(asn), HoldTime(hold_time), RouterID(router_id), Capabilities.unpack(data[9:]) )
def new_open(self): if self.neighbor['local-as']: local_as = self.neighbor['local-as'] elif self.negotiated.received_open: local_as = self.negotiated.received_open.asn else: raise RuntimeError('no ASN available for the OPEN message') sent_open = Open( Version(4), local_as, self.neighbor['hold-time'], self.neighbor['router-id'], Capabilities().new(self.neighbor, self.peer._restarted), ) # we do not buffer open message in purpose for _ in self.write(sent_open): yield _NOP log.debug('>> %s' % sent_open, self.connection.session()) 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 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(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 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
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
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
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.ID.ADD_PATH] = path capa[Capability.ID.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, e: logger.parser('could not parse the message') logger.parser(str(e)) return False except Exception, e: logger.parser('could not parse the message') logger.parser(str(e)) return False
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(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) # 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('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_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
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:]))