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
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
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
def _negotiated(neighbor): 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 return negotiated
def setUp (self): # env.log.all = True 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_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(4,neighbor.local_as,routerid_1,capa,180) o2 = Open(4,neighbor.peer_as,routerid_2,capa,180) 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,exc: logger.parser('could not parse the message') logger.parser(str(exc)) return False except Exception,exc: logger.parser('could not parse the message') logger.parser(str(exc)) return False
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.string),capa) o2 = Open(Version(4),ASN(neighbor.peer_as),HoldTime(180),RouterID(neighbor.peer_address.string),capa) negotiated = Negotiated(neighbor) negotiated.sent(o1) negotiated.received(o2) self.negotiated[asn4] = negotiated
class Transcoder(object): seen_open = { 'send': None, 'receive': None, } negotiated = None json = Response.JSON(json_version) def __init__(self, src='json', dst='json'): if src != 'json': raise RuntimeError('left as an exercise to the reader') if dst != 'json': raise RuntimeError('left as an exercise to the reader') self.convert = self._from_json self.encoder = self.json def _state(self): self.seen_open['send'] = None self.seen_open['receive'] = None self.negotiated = None def _open(self, direction, message): self.seen_open[direction] = message if all(self.seen_open.values()): self.negotiated = Negotiated(None) self.negotiated.sent(self.seen_open['send']) self.negotiated.received(self.seen_open['receive']) def _from_json(self, direction, json_string): try: parsed = json.loads(json_string) except ValueError: print('invalid JSON message', file=sys.stderr) sys.exit(1) if parsed.get('exabgp', '0.0.0') != json_version: print('invalid json version', json_string, file=sys.stderr) sys.exit(1) content = parsed.get('type', '') if not content: print('invalid json content', json_string, file=sys.stderr) 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 json_string direction = parsed['neighbor']['direction'] category = parsed['neighbor']['message']['category'] header = parsed['neighbor']['message']['header'] body = parsed['neighbor']['message']['body'] data = b''.join(bytes([int(body[_ : _ + 2], 16)]) for _ in range(0, len(body), 2)) if content == 'open': message = Open.unpack_message(data) self._open(direction, message) return self.encoder.open(neighbor, direction, message, None, header, body) if content == 'keepalive': return self.encoder.keepalive(neighbor, direction, None, header, body) if content == 'notification': # XXX: Use the code of the Notifcation class here .. message = Notification.unpack_message(data) if (message.code, message.subcode) != (6, 2): message.data = data if not len([_ for _ in data if _ not in string.printable]) else hexstring(data) return self.encoder.notification(neighbor, direction, message, None, header, body) if len(data) == 0: # shutdown without shutdown communication (the old fashioned way) message.data = '' return self.encoder.notification(neighbor, direction, message, None, header, body) # draft-ietf-idr-shutdown or the peer was using 6,2 with data shutdown_length = data[0] data = data[1:] if shutdown_length == 0: message.data = "empty Shutdown Communication." # move offset past length field return self.encoder.notification(neighbor, direction, message, None, header, body) if len(data) < shutdown_length: message.data = "invalid Shutdown Communication (buffer underrun) length : %i [%s]" % ( shutdown_length, hexstring(data), ) return self.encoder.notification(neighbor, direction, message, None, header, body) if shutdown_length > 128: message.data = "invalid Shutdown Communication (too large) length : %i [%s]" % ( shutdown_length, hexstring(data), ) return self.encoder.notification(neighbor, direction, message, None, header, body) try: message.data = 'Shutdown Communication: "%s"' % data[:shutdown_length].decode('utf-8').replace( '\r', ' ' ).replace('\n', ' ') except UnicodeDecodeError: message.data = "invalid Shutdown Communication (invalid UTF-8) length : %i [%s]" % ( shutdown_length, hexstring(data), ) return self.encoder.notification(neighbor, direction, message, None, header, body) trailer = data[shutdown_length:] if trailer: message.data += ", trailing data: " + hexstring(trailer) return self.encoder.notification(neighbor, direction, message, None, header, body) if not self.negotiated: print('invalid message sequence, open not exchange not complete', json_string, file=sys.stderr) sys.exit(1) message = Message.unpack(category, data, direction, self.negotiated) if content == 'update': return self.encoder.update(neighbor, direction, message, None, header, body) if content == 'eor': # XXX: Should not be required return self.encoder.update(neighbor, direction, message, None, header, body) if content == 'refresh': return self.json.refresh(neighbor, direction, message, None, header, body) if content == 'operational': return self.json.refresh(neighbor, direction, message, None, header, body) raise RuntimeError('the programer is a monkey and forgot a JSON message type')
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 (neighbors): logger = Logger() logger._option.parser = True 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() 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.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)) 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','') 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 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
class Transcoder (object): seen_open = { 'send': None, 'receive': None, } negotiated = None json = Response.JSON(json_version) def __init__ (self, src='json', dst='json'): if src != 'json': raise RuntimeError('left as an exercise to the reader') if dst != 'json': raise RuntimeError('left as an exercise to the reader') self.convert = self._from_json self.encoder = self.json def _state (self): self.seen_open['send'] = None self.seen_open['receive'] = None self.negotiated = None def _open (self,direction,message): self.seen_open[direction] = message if all(self.seen_open.values()): self.negotiated = Negotiated(None) self.negotiated.sent(self.seen_open['send']) self.negotiated.received(self.seen_open['receive']) def _from_json (self, json_string): try: parsed = json.loads(json_string) except ValueError: print('invalid JSON message', file=sys.stderr) sys.exit(1) if parsed.get('exabgp','0.0.0') != json_version: print('invalid json version', json_string, file=sys.stderr) sys.exit(1) content = parsed.get('type','') if not content: print('invalid json content', json_string, file=sys.stderr) 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 json_string direction = parsed['neighbor']['direction'] category = parsed['neighbor']['message']['category'] header = parsed['neighbor']['message']['header'] body = parsed['neighbor']['message']['body'] data = concat_bytes_i(character(int(body[_:_+2],16)) for _ in range(0,len(body),2)) if content == 'open': message = Open.unpack_message(data) self._open(direction,message) return self.encoder.open(neighbor,direction,message,None,header,body) if content == 'keepalive': return self.encoder.keepalive(neighbor,direction,None,header,body) if content == 'notification': # XXX: Use the code of the Notifcation class here .. message = Notification.unpack_message(data) if (message.code, message.subcode) != (6, 2): message.data = data if not len([_ for _ in data if _ not in string.printable]) else hexstring(data) return self.encoder.notification(neighbor,direction,message,None,header,body) if len(data) == 0: # shutdown without shutdown communication (the old fashioned way) message.data = '' return self.encoder.notification(neighbor,direction,message,None,header,body) # draft-ietf-idr-shutdown or the peer was using 6,2 with data shutdown_length = ordinal(data[0]) data = data[1:] if shutdown_length == 0: message.data = "empty Shutdown Communication." # move offset past length field return self.encoder.notification(neighbor,direction,message,None,header,body) if len(data) < shutdown_length: message.data = "invalid Shutdown Communication (buffer underrun) length : %i [%s]" % (shutdown_length, hexstring(data)) return self.encoder.notification(neighbor,direction,message,None,header,body) if shutdown_length > 128: message.data = "invalid Shutdown Communication (too large) length : %i [%s]" % (shutdown_length, hexstring(data)) return self.encoder.notification(neighbor,direction,message,None,header,body) try: message.data = 'Shutdown Communication: "%s"' % \ data[:shutdown_length].decode('utf-8').replace('\r',' ').replace('\n',' ') except UnicodeDecodeError: message.data = "invalid Shutdown Communication (invalid UTF-8) length : %i [%s]" % (shutdown_length, hexstring(data)) return self.encoder.notification(neighbor,direction,message,None,header,body) trailer = data[shutdown_length:] if trailer: message.data += ", trailing data: " + hexstring(trailer) return self.encoder.notification(neighbor,direction,message,None,header,body) if not self.negotiated: print('invalid message sequence, open not exchange not complete', json_string, file=sys.stderr) sys.exit(1) message = Message.unpack(category,data,self.negotiated) if content == 'update': return self.encoder.update(neighbor, direction, message, None, header,body) if content == 'eor': # XXX: Should not be required return self.encoder.update(neighbor, direction, message, None, header,body) if content == 'refresh': return self.json.refresh(neighbor, direction, message, None, header,body) if content == 'operational': return self.json.refresh(neighbor, direction, message, None, header,body) raise RuntimeError('the programer is a monkey and forgot a JSON message type')
class Transcoder(object): seen_open = { 'send': None, 'receive': None, } negotiated = None json = Response.JSON(json_version) def __init__(self, src='json', dst='json'): if src != 'json': raise RuntimeError('left as an exercise to the reader') if dst != 'json': raise RuntimeError('left as an exercise to the reader') self.convert = self._from_json self.encoder = self.json def _state(self): self.seen_open['send'] = None self.seen_open['receive'] = None self.negotiated = None def _open(self, direction, message): self.seen_open[direction] = message if all(self.seen_open.values()): self.negotiated = Negotiated(None) self.negotiated.sent(self.seen_open['send']) self.negotiated.received(self.seen_open['receive']) 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': message = Notification.unpack_message(raw) return self.encoder.notification(neighbor, direction, message, 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_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 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(4, neighbor.local_as, routerid_1, capa, 180) o2 = Open(4, neighbor.peer_as, routerid_2, capa, 180) 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, exc: logger.parser('could not parse the message') logger.parser(str(exc)) return False except Exception, exc: logger.parser('could not parse the message') logger.parser(str(exc)) return False
class Transcoder (object): seen_open = { 'send': None, 'receive': None, } negotiated = None json = Response.JSON(json_version) def __init__ (self, src='json', dst='json'): if src != 'json': raise RuntimeError('left as an exercise to the reader') if dst != 'json': raise RuntimeError('left as an exercise to the reader') self.convert = self._from_json self.encoder = self.json def _state (self): self.seen_open['send'] = None self.seen_open['receive'] = None self.negotiated = None def _open (self,direction,message): self.seen_open[direction] = message if all(self.seen_open.values()): self.negotiated = Negotiated(None) self.negotiated.sent(self.seen_open['send']) self.negotiated.received(self.seen_open['receive']) 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': message = Notification.unpack_message(raw) return self.encoder.notification(neighbor,direction,message,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')