Esempio n. 1
0
	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
Esempio n. 2
0
	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)
Esempio n. 3
0
    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)
Esempio n. 4
0
	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)
Esempio n. 5
0
	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])
Esempio n. 6
0
    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])
Esempio n. 7
0
    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)
Esempio n. 8
0
    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')
Esempio n. 9
0
            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)
Esempio n. 10
0
	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')
Esempio n. 11
0
    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
Esempio n. 12
0
    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')
Esempio n. 13
0
    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
Esempio n. 14
0
	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
Esempio n. 15
0
                    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)
Esempio n. 16
0
	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')