def reader (self): # _reader returns the whole number requested or nothing and then stops for header in self._reader(Message.HEADER_LEN): if not header: yield 0,0,'','' if not header.startswith(Message.MARKER): raise NotifyError(1,1,'The packet received does not contain a BGP marker') msg = ord(header[18]) length = unpack('!H',header[16:18])[0] if length < Message.HEADER_LEN or length > Message.MAX_LEN: raise NotifyError(1,2,'%s has an invalid message length of %d' %(Message().name(msg),length)) validator = Message.Length.get(msg,lambda _ : _ >= 19) if not validator(length): # MUST send the faulty msg_length back raise NotifyError(1,2,'%s has an invalid message length of %d' %(Message().name(msg),msg_length)) number = length - Message.HEADER_LEN if not number: yield length,msg,header,'' return for body in self._reader(number): if not body: yield 0,0,'','' yield length,msg,header,body
def read_message (self): for length,msg,header,body,notify in self.connection.reader(): if notify: if self.neighbor.api['receive-packets']: self.peer.reactor.processes.receive(self.peer,msg,header,body) if self.neighbor.api[Message.ID.NOTIFICATION]: self.peer.reactor.processes.notification(self.peer,notify.code,notify.subcode,str(notify)) # XXX: is notify not already Notify class ? raise Notify(notify.code,notify.subcode,str(notify)) if not length: yield _NOP if self.neighbor.api['receive-packets'] and not self.neighbor.api['consolidate']: self.peer.reactor.processes.receive(self.peer,msg,header,body) if msg == Message.ID.UPDATE and not self.neighbor.api['receive-parsed'] and not self.log_routes: yield _UPDATE return self.logger.message(self.me('<< %s' % Message.ID.name(msg))) try: message = Message.unpack_message(msg,body,self.negotiated) except (KeyboardInterrupt,SystemExit,Notify): raise except Exception,e: self.logger.message(self.me('Could not decode message %s' % Capability.hex(msg))) self.logger.message(self.me('%s' % str(e))) raise Notify(2,0,'can not decode update message %s' % Capability.hex(msg))
def read_message (self): # This will always be defined by the loop but scope leaking upset scrutinizer/pylint msg_id = None packets = self.neighbor.api['receive-packets'] consolidate = self.neighbor.api['receive-consolidate'] parsed = self.neighbor.api['receive-parsed'] body,header = '','' # just because pylint/pylama are getting more clever for length,msg_id,header,body,notify in self.connection.reader(): # internal issue if notify: if self.neighbor.api.get('send-%s' % Message.CODE.NOTIFICATION.SHORT,False): if consolidate: self.peer.reactor.processes.notification(self.peer.neighbor,'send',notify.code,notify.subcode,str(notify),header,body) elif parsed: self.peer.reactor.processes.notification(self.peer.neighbor,'send',notify.code,notify.subcode,str(notify),'','') elif packets: self.peer.reactor.processes.packets(self.peer.neighbor,'send',msg_id,header,body) # XXX: is notify not already Notify class ? raise Notify(notify.code,notify.subcode,str(notify)) if not length: yield _NOP continue self.logger.message(self.me('<< %s' % Message.CODE.name(msg_id))) for_api = self.neighbor.api.get('receive-%s' % Message.CODE.short(msg_id),False) if for_api and packets and not consolidate: self.peer.reactor.processes.packets(self.peer.neighbor,'receive',msg_id,header,body) if msg_id == Message.CODE.UPDATE: if not (for_api or self.log_routes) and not (parsed or consolidate): yield _UPDATE return try: message = Message.unpack(msg_id,body,self.negotiated) except (KeyboardInterrupt,SystemExit,Notify): raise except Exception,exc: self.logger.message(self.me('Could not decode message "%d"' % msg_id)) self.logger.message(self.me('%s' % str(exc))) self.logger.message(traceback.format_exc()) raise Notify(1,0,'can not decode update message of type "%d"' % msg_id) # raise Notify(5,0,'unknown message received') if for_api: if consolidate: self.peer.reactor.processes.message(msg_id,self.neighbor,'receive',message,header,body) elif parsed: self.peer.reactor.processes.message(msg_id,self.neighbor,'receive',message,'','') if message.TYPE == Notification.TYPE: raise message yield message
def read_message (self,comment=''): self.peer.reactor.processes.increase(self.peer) for length,msg,header,body,notify in self.connection.reader(): if notify: if self.neighbor.api['receive-packets']: self.peer.reactor.processes.receive(self.peer,msg,header,body) if self.neighbor.api[Message.ID.NOTIFICATION]: self.peer.reactor.processes.notification(self.peer,notify.code,notify.subcode,str(notify)) # XXX: is notify not already Notify class ? raise Notify(notify.code,notify.subcode,str(notify)) if not length: yield _NOP if self.neighbor.api['receive_packets']: self.peer.reactor.processes.receive(self.peer,msg,header,body) if msg == Message.ID.UPDATE and not self.neighbor.api['receive-parsed'] and not self.log_routes: yield _UPDATE return message = Message.unpack_message(msg,body,self.negotiated) self.logger.message(self.me('<< %s' % Message.ID.name(msg))) if self.neighbor.api[msg]: if self.neighbor.api['receive-parsed']: if self.neighbor.api['consolidate'] and self.neighbor.api['receive-packets']: self.peer.reactor.processes.message(msg,self.peer,message,header,body) else: self.peer.reactor.processes.message(msg,self.peer,message,'','') yield message return # XXX: FIXME: check it is well 2,4 raise Notify(2,4,'unknown message received')
def read_message(self): for length, msg, header, body, notify in self.connection.reader(): if notify: if self.neighbor.api['receive-packets']: self.peer.reactor.processes.receive( self.peer, msg, header, body) if self.neighbor.api[Message.ID.NOTIFICATION]: self.peer.reactor.processes.notification( self.peer, notify.code, notify.subcode, str(notify)) # XXX: is notify not already Notify class ? raise Notify(notify.code, notify.subcode, str(notify)) if not length: yield _NOP if self.neighbor.api[ 'receive-packets'] and not self.neighbor.api['consolidate']: self.peer.reactor.processes.receive(self.peer, msg, header, body) if msg == Message.ID.UPDATE and not self.neighbor.api[ 'receive-parsed'] and not self.log_routes: yield _UPDATE return self.logger.message(self.me('<< %s' % Message.ID.name(msg))) try: message = Message.unpack_message(msg, body, self.negotiated) except (KeyboardInterrupt, SystemExit, Notify): raise except Exception, e: self.logger.message( self.me('Could not decode message %s' % Capability.hex(msg))) self.logger.message(self.me('%s' % str(e))) raise Notify( 2, 0, 'can not decode update message %s' % Capability.hex(msg))
def read_message (self): # This will always be defined by the loop but scope leaking upset scrutinizer/pylint msg_id = None for length,msg_id,header,body,notify in self.connection.reader(): if notify: if self.neighbor.api['receive-packets']: self.peer.reactor.processes.receive(self.peer,msg_id,header,body) if self.neighbor.api[Message.CODE.NOTIFICATION]: self.peer.reactor.processes.notification(self.peer,notify.code,notify.subcode,str(notify)) # XXX: is notify not already Notify class ? raise Notify(notify.code,notify.subcode,str(notify)) if not length: yield _NOP if self.neighbor.api['receive-packets'] and not self.neighbor.api['consolidate']: self.peer.reactor.processes.receive(self.peer,msg_id,header,body) if msg_id == Message.CODE.UPDATE and not self.neighbor.api['receive-parsed'] and not self.log_routes: yield _UPDATE return self.logger.message(self.me('<< %s' % Message.CODE.name(msg_id))) try: message = Message.unpack(msg_id,body,self.negotiated) except (KeyboardInterrupt,SystemExit,Notify): raise except Exception,exc: self.logger.message(self.me('Could not decode message "%d"' % msg_id)) self.logger.message(self.me('%s' % str(exc))) # XXX: TODO: add backtrace here raise Notify(1,0,'can not decode update message of type "%d"' % msg_id)
def send (self, peer, category, header, body): return self._header(self._neighbor(peer,self._kv({ 'message':'{ %s } ' % self._kv({ 'sent': category, 'header': hexstring(header), 'body': hexstring(body), }) })),'','',peer.neighbor.identificator(),self.count(peer),message_type=Message.string(category))
def packets (self, neighbor, direction, category, header, body): return self._header(self._neighbor(neighbor,direction,self._kv({ 'message': '{ %s } ' % self._kv({ 'category': category, 'header': hexstring(header), 'body': hexstring(body), }) })),'','',neighbor,message_type=Message.string(category))
def command (self, scope, name, command, tokens): if command in ('packets','parsed','consolidate','neighbor-changes'): scope[-1]['%s-%s' % (name,command)] = True return True message = Message.from_string(command) if message == Message.CODE.NOP: return self.error.set('unknown process message') scope[-1]['%s-%d' % (name,message)] = True return True
def command(self, scope, name, command, tokens): if command in ("packets", "parsed", "consolidate", "neighbor-changes"): scope[-1]["%s-%s" % (name, command)] = True return True message = Message.from_string(command) if message == Message.CODE.NOP: return self.error.set("unknown process message") scope[-1]["%s-%d" % (name, message)] = True return True
def read_message(self): # This will always be defined by the loop but scope leaking upset scrutinizer/pylint msg_id = None packets = self.neighbor.api['receive-packets'] consolidate = self.neighbor.api['receive-consolidate'] parsed = self.neighbor.api['receive-parsed'] body, header = '', '' # just because pylint/pylama are getting more clever for length, msg_id, header, body, notify in self.connection.reader(): if notify: if self.neighbor.api['receive-%s' % Message.CODE.NOTIFICATION.SHORT]: if packets and not consolidate: self.peer.reactor.processes.packets( self.peer.neighbor, 'receive', msg_id, header, body) if not packets or consolidate: header = '' body = '' self.peer.reactor.processes.notification( self.peer.neighbor, 'receive', notify.code, notify.subcode, str(notify), header, body) # XXX: is notify not already Notify class ? raise Notify(notify.code, notify.subcode, str(notify)) if not length: yield _NOP if packets and not consolidate: self.peer.reactor.processes.packets(self.peer.neighbor, 'receive', msg_id, header, body) if msg_id == Message.CODE.UPDATE: if not parsed and not self.log_routes: yield _UPDATE return self.logger.message(self.me('<< %s' % Message.CODE.name(msg_id))) try: message = Message.unpack(msg_id, body, self.negotiated) except (KeyboardInterrupt, SystemExit, Notify): raise except Exception, exc: self.logger.message( self.me('Could not decode message "%d"' % msg_id)) self.logger.message(self.me('%s' % str(exc))) self.logger.message(traceback.format_exc()) raise Notify(1, 0, 'can not decode update message of type "%d"' % msg_id)
def packets (self, neighbor, direction, category, negotiated, header, body): message = { 'message': '{ %s } ' % self._kv({ 'category': category, 'header': hexstring(header), 'body': hexstring(body), }) } if negotiated: message.update(self._negotiated(negotiated)) return self._header(self._neighbor(neighbor,direction,self._kv( message )),'','',neighbor,message_type=Message.string(category))
def read_message (self): # This will always be defined by the loop but scope leaking upset scrutinizer/pylint msg_id = None packets = self.neighbor.api['receive-packets'] consolidate = self.neighbor.api['receive-consolidate'] parsed = self.neighbor.api['receive-parsed'] body,header = '','' # just because pylint/pylama are getting more clever for length,msg_id,header,body,notify in self.connection.reader(): if notify: if self.neighbor.api['receive-%s' % Message.CODE.NOTIFICATION.SHORT]: if packets and not consolidate: self.peer.reactor.processes.packets(self.peer.neighbor,'receive',msg_id,header,body) if not packets or consolidate: header = '' body = '' self.peer.reactor.processes.notification(self.peer.neighbor,'receive',notify.code,notify.subcode,str(notify),header,body) # XXX: is notify not already Notify class ? raise Notify(notify.code,notify.subcode,str(notify)) if not length: yield _NOP if packets and not consolidate: self.peer.reactor.processes.packets(self.peer.neighbor,'receive',msg_id,header,body) if msg_id == Message.CODE.UPDATE: if not parsed and not self.log_routes: yield _UPDATE return self.logger.message(self.me('<< %s' % Message.CODE.name(msg_id))) try: message = Message.unpack(msg_id,body,self.negotiated) except (KeyboardInterrupt,SystemExit,Notify): raise except Exception,exc: self.logger.message(self.me('Could not decode message "%d"' % msg_id)) self.logger.message(self.me('%s' % str(exc))) self.logger.message(traceback.format_exc()) raise Notify(1,0,'can not decode update message of type "%d"' % msg_id)
def read_message(self, comment=''): for length, msg, header, body, notify in self.connection.reader(): if notify: if self.neighbor.api['receive-packets']: self.peer.reactor.processes.receive( self.peer, msg, header, body) if self.neighbor.api[Message.ID.NOTIFICATION]: self.peer.reactor.processes.notification( self.peer, notify.code, notify.subcode, str(notify)) # XXX: is notify not already Notify class ? raise Notify(notify.code, notify.subcode, str(notify)) if not length: yield _NOP if self.neighbor.api[ 'receive-packets'] and not self.neighbor.api['consolidate']: self.peer.reactor.processes.receive(self.peer, msg, header, body) if msg == Message.ID.UPDATE and not self.neighbor.api[ 'receive-parsed'] and not self.log_routes: yield _UPDATE return message = Message.unpack_message(msg, body, self.negotiated) self.logger.message(self.me('<< %s' % Message.ID.name(msg))) if message.TYPE == Notification.TYPE: raise message if self.neighbor.api[msg]: if self.neighbor.api['receive-parsed']: if self.neighbor.api['consolidate'] and self.neighbor.api[ 'receive-packets']: self.peer.reactor.processes.message( msg, self.peer, message, header, body) else: self.peer.reactor.processes.message( msg, self.peer, message, '', '') yield message return # XXX: FIXME: check it is well 2,4 raise Notify(2, 4, 'unknown message received')
def test_1_open (self): check_capa = { 1: [(AFI.ipv4, SAFI.unicast), (AFI.ipv6, SAFI.unicast)], 2: RouteRefresh(), 65: 65534, 128: RouteRefresh(), } message_id = 1 negotiated = {'invalid':'test'} o = Message.unpack(message_id,data_from_body(open_body),negotiated) self.assertEqual(o.version,4) self.assertEqual(o.asn,65534) self.assertEqual(o.router_id,RouterID('0.0.0.0')) self.assertEqual(o.hold_time,180) for k,v in o.capabilities.items(): self.assertEqual(v,check_capa[k])
def test_1_open(self): check_capa = { 1: [(AFI.ipv4, SAFI.unicast), (AFI.ipv6, SAFI.unicast)], 2: RouteRefresh(), 65: 65534, 128: RouteRefresh(), } message_id = 1 negotiated = {'invalid': 'test'} o = Message.unpack(message_id, data_from_body(open_body), negotiated) self.assertEqual(o.version, 4) self.assertEqual(o.asn, 65534) self.assertEqual(o.router_id, RouterID('0.0.0.0')) self.assertEqual(o.hold_time, 180) for k, v in o.capabilities.items(): self.assertEqual(v, check_capa[k])
def read_message(self): # This will always be defined by the loop but scope leaking upset scrutinizer/pylint msg_id = None for length, msg_id, header, body, notify in self.connection.reader(): if notify: if self.neighbor.api['receive-packets']: self.peer.reactor.processes.receive( self.peer, msg_id, header, body) if self.neighbor.api[Message.CODE.NOTIFICATION]: self.peer.reactor.processes.notification( self.peer, notify.code, notify.subcode, str(notify)) # XXX: is notify not already Notify class ? raise Notify(notify.code, notify.subcode, str(notify)) if not length: yield _NOP if self.neighbor.api[ 'receive-packets'] and not self.neighbor.api['consolidate']: self.peer.reactor.processes.receive(self.peer, msg_id, header, body) if msg_id == Message.CODE.UPDATE and not self.neighbor.api[ 'receive-parsed'] and not self.log_routes: yield _UPDATE return self.logger.message(self.me('<< %s' % Message.CODE.name(msg_id))) try: message = Message.unpack(msg_id, body, self.negotiated) except (KeyboardInterrupt, SystemExit, Notify): raise except Exception, exc: self.logger.message( self.me('Could not decode message "%d"' % msg_id)) self.logger.message(self.me('%s' % str(exc))) # XXX: TODO: add backtrace here raise Notify(1, 0, 'can not decode update message of type "%d"' % msg_id)
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')
65: 65534L, 128: RouteRefresh(), } message_id = 1 body = ''.join([ chr(c) for c in [ 0x4, 0xff, 0xfe, 0x0, 0xb4, 0x0, 0x0, 0x0, 0x0, 0x20, 0x2, 0x6, 0x1, 0x4, 0x0, 0x1, 0x0, 0x1, 0x2, 0x6, 0x1, 0x4, 0x0, 0x2, 0x0, 0x1, 0x2, 0x2, 0x80, 0x0, 0x2, 0x2, 0x2, 0x0, 0x2, 0x6, 0x41, 0x4, 0x0, 0x0, 0xff, 0xfe ] ]) negotiated = {'invalid': 'test'} o = Message.unpack(message_id, body, negotiated) self.assertEqual(o.version, 4) self.assertEqual(o.asn, 65534) self.assertEqual(o.router_id, RouterID('0.0.0.0')) self.assertEqual(o.hold_time, 180) for k, v in o.capabilities.items(): self.assertEqual(v, check_capa[k]) 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)
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 read_message(self): # This will always be defined by the loop but scope leaking upset scrutinizer/pylint msg_id = None packets = self.neighbor.api['receive-packets'] consolidate = self.neighbor.api['receive-consolidate'] parsed = self.neighbor.api['receive-parsed'] body, header = '', '' # just because pylint/pylama are getting more clever for length, msg_id, header, body, notify in self.connection.reader(): # internal issue if notify: if self.neighbor.api.get( 'send-%s' % Message.CODE.NOTIFICATION.SHORT, False): if consolidate: self.peer.reactor.processes.notification( self.peer.neighbor, 'send', notify.code, notify.subcode, str(notify), header, body) elif parsed: self.peer.reactor.processes.notification( self.peer.neighbor, 'send', notify.code, notify.subcode, str(notify), '', '') elif packets: self.peer.reactor.processes.packets( self.peer.neighbor, 'send', msg_id, header, body) # XXX: is notify not already Notify class ? raise Notify(notify.code, notify.subcode, str(notify)) if not length: yield _NOP continue self.logger.message(self.me('<< %s' % Message.CODE.name(msg_id))) for_api = self.neighbor.api.get( 'receive-%s' % Message.CODE.short(msg_id), False) if for_api and packets and not consolidate: self.peer.reactor.processes.packets(self.peer.neighbor, 'receive', msg_id, header, body) if msg_id == Message.CODE.UPDATE: if not (for_api or self.log_routes) and not (parsed or consolidate): yield _UPDATE return try: message = Message.unpack(msg_id, body, self.negotiated) except (KeyboardInterrupt, SystemExit, Notify): raise except Exception, exc: self.logger.message( self.me('Could not decode message "%d"' % msg_id)) self.logger.message(self.me('%s' % str(exc))) self.logger.message(traceback.format_exc()) raise Notify( 1, 0, 'can not decode update message of type "%d"' % msg_id) # raise Notify(5,0,'unknown message received') if for_api: if consolidate: self.peer.reactor.processes.message( msg_id, self.neighbor, 'receive', message, header, body) elif parsed: self.peer.reactor.processes.message( msg_id, self.neighbor, 'receive', message, '', '') if message.TYPE == Notification.TYPE: raise message yield message
def _message (self,data): return Message._message(self,"%s%s%s" % ( self.what.pack(), pack('!H',len(data)), data ))
0x2, 0x0, 0x2, 0x6, 0x41, 0x4, 0x0, 0x0, 0xFF, 0xFE, ] ] ) negotiated = {"invalid": "test"} o = Message.unpack(message_id, body, negotiated) self.assertEqual(o.version, 4) self.assertEqual(o.asn, 65534) self.assertEqual(o.router_id, RouterID("0.0.0.0")) self.assertEqual(o.hold_time, 180) for k, v in o.capabilities.items(): self.assertEqual(v, check_capa[k]) def test_2_open(self): capabilities = Capabilities() o = Open(Version(4), ASN(65500), HoldTime(180), RouterID("127.0.0.1"), capabilities) 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)
def __init__ (self,what): Message.__init__(self) self.what = Type(what)
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 _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 _message(self, data): return Message._message( self, "%s%s%s" % (self.what.pack(), pack('!H', len(data)), data))
def __init__(self, what): Message.__init__(self) self.what = Type(what)
def read_message(self): # This will always be defined by the loop but scope leaking upset scrutinizer/pylint msg_id = None packets = self.neighbor.api['receive-packets'] consolidate = self.neighbor.api['receive-consolidate'] parsed = self.neighbor.api['receive-parsed'] body, header = b'', b'' # just because pylint/pylama are getting more clever for length, msg_id, header, body, notify in self.connection.reader(): # internal issue if notify: code = 'receive-%s' % Message.CODE.NOTIFICATION.SHORT if self.neighbor.api.get(code, False): if consolidate: self.peer.reactor.processes.notification( self.peer.neighbor, 'receive', notify.code, notify.subcode, str(notify), None, header, body) elif parsed: self.peer.reactor.processes.notification( self.peer.neighbor, 'receive', notify.code, notify.subcode, str(notify), None, b'', b'') elif packets: self.peer.reactor.processes.packets( self.peer.neighbor, 'receive', msg_id, None, header, body) # XXX: is notify not already Notify class ? raise Notify(notify.code, notify.subcode, str(notify)) if not length: yield _NOP continue log.debug('<< message of type %s' % Message.CODE.name(msg_id), self.connection.session()) code = 'receive-%s' % Message.CODE.short(msg_id) self.peer.stats[code] = self.peer.stats.get(code, 0) + 1 for_api = self.neighbor.api.get(code, False) if for_api and packets and not consolidate: negotiated = self.negotiated if self.neighbor.api.get( 'negotiated', False) else None self.peer.reactor.processes.packets(self.peer.neighbor, 'receive', msg_id, negotiated, header, body) if msg_id == Message.CODE.UPDATE: if not self.neighbor['adj-rib-in'] and not ( for_api or self.log_routes) and not (parsed or consolidate): yield _UPDATE return try: message = Message.unpack(msg_id, body, Direction.IN, self.negotiated) except (KeyboardInterrupt, SystemExit, Notify): raise except Exception as exc: log.debug('could not decode message "%d"' % msg_id, self.connection.session()) log.debug('%s' % str(exc), self.connection.session()) log.debug(traceback.format_exc(), self.connection.session()) raise Notify( 1, 0, 'can not decode update message of type "%d"' % msg_id) # raise Notify(5,0,'unknown message received') if message.TYPE == Update.TYPE: if Attribute.CODE.INTERNAL_TREAT_AS_WITHDRAW in message.attributes: for nlri in message.nlris: nlri.action = IN.WITHDRAWN if for_api: negotiated = self.negotiated if self.neighbor.api.get( 'negotiated', False) else None if consolidate: self.peer.reactor.processes.message( msg_id, self.neighbor, 'receive', message, negotiated, header, body) elif parsed: self.peer.reactor.processes.message( msg_id, self.neighbor, 'receive', message, negotiated, b'', b'') if message.TYPE == Notification.TYPE: raise message if message.TYPE == Update.TYPE and Attribute.CODE.INTERNAL_DISCARD in message.attributes: yield _NOP else: yield message
def read_message (self): # This will always be defined by the loop but scope leaking upset scrutinizer/pylint msg_id = None packets = self.neighbor.api['receive-packets'] consolidate = self.neighbor.api['receive-consolidate'] parsed = self.neighbor.api['receive-parsed'] body,header = b'',b'' # just because pylint/pylama are getting more clever for length,msg_id,header,body,notify in self.connection.reader(): # internal issue if notify: code = 'receive-%s' % Message.CODE.NOTIFICATION.SHORT if self.neighbor.api.get(code,False): if consolidate: self.peer.reactor.processes.notification(self.peer.neighbor,'receive',notify.code,notify.subcode,str(notify),None,header,body) elif parsed: self.peer.reactor.processes.notification(self.peer.neighbor,'receive',notify.code,notify.subcode,str(notify),None,b'',b'') elif packets: self.peer.reactor.processes.packets(self.peer.neighbor,'receive',msg_id,None,header,body) # XXX: is notify not already Notify class ? raise Notify(notify.code,notify.subcode,str(notify)) if not length: yield _NOP continue self.logger.debug('<< message of type %s' % Message.CODE.name(msg_id),self.connection.session()) code = 'receive-%s' % Message.CODE.short(msg_id) self.peer.stats[code] = self.peer.stats.get(code,0) + 1 for_api = self.neighbor.api.get(code,False) if for_api and packets and not consolidate: negotiated = self.negotiated if self.neighbor.api.get('negotiated',False) else None self.peer.reactor.processes.packets(self.peer.neighbor,'receive',msg_id,negotiated,header,body) if msg_id == Message.CODE.UPDATE: if not self.neighbor.adj_rib_in and not (for_api or self.log_routes) and not (parsed or consolidate): yield _UPDATE return try: message = Message.unpack(msg_id,body,self.negotiated) except (KeyboardInterrupt,SystemExit,Notify): raise except Exception as exc: self.logger.debug('could not decode message "%d"' % msg_id,self.connection.session()) self.logger.debug('%s' % str(exc),self.connection.session()) self.logger.debug(traceback.format_exc(),self.connection.session()) raise Notify(1,0,'can not decode update message of type "%d"' % msg_id) # raise Notify(5,0,'unknown message received') if message.TYPE == Update.TYPE: if Attribute.CODE.INTERNAL_TREAT_AS_WITHDRAW in message.attributes: for nlri in message.nlris: nlri.action = IN.WITHDRAWN if for_api: negotiated = self.negotiated if self.neighbor.api.get('negotiated',False) else None if consolidate: self.peer.reactor.processes.message(msg_id,self.neighbor,'receive',message,negotiated,header,body) elif parsed: self.peer.reactor.processes.message(msg_id,self.neighbor,'receive',message,negotiated,b'',b'') if message.TYPE == Notification.TYPE: raise message if message.TYPE == Update.TYPE and Attribute.CODE.INTERNAL_DISCARD in message.attributes: yield _NOP else: yield message