Beispiel #1
0
    def _header_body(self, header, body):
        header = ' header %s' % hexstring(header) if header else ''
        body = ' body %s' % hexstring(body) if body else ''

        total_string = header + body if body else header

        return total_string
Beispiel #2
0
    def _header(self, content, header, body, neighbor, message_type=None):
        peer = '"host" : "%s", ' % socket.gethostname()
        pid = '"pid" : %s, ' % os.getpid()
        ppid = '"ppid" : %s, ' % os.getppid()
        counter = '"counter": %s, ' % self._counter(
            neighbor) if neighbor is not None else ''
        header = '"header": "%s", ' % hexstring(header) if header else ''
        body = '"body": "%s", ' % hexstring(body) if body else ''
        mtype = '"type": "%s", ' % message_type if message_type else 'default'

        return \
         '{ '\
         '"exabgp": "%s", '\
         '"time": %s, ' \
         '%s%s%s%s%s%s%s%s ' \
         '}' % (
          self.version,
          self.time(time.time()),
          peer,
          pid,
          ppid,
          counter,
          mtype,
          header,
          body,
          content
         )
Beispiel #3
0
	def _header_body (self, header, body):
		header = ' header %s' % hexstring(header) if header else ''
		body = ' body %s' % hexstring(body) if body else ''

		total_string = header+body if body else header

		return total_string
Beispiel #4
0
	def _header (self, content, header, body, neighbor,message_type=None):
		peer     = '"host" : "%s", '   % socket.gethostname()
		pid      = '"pid" : %s, '      % os.getpid()
		ppid     = '"ppid" : %s, '     % os.getppid()
		counter  = '"counter": %s, '   % self._counter(neighbor) if neighbor is not None else ''
		header   = '"header": "%s", '  % hexstring(header) if header else ''
		body     = '"body": "%s", '    % hexstring(body) if body else ''
		mtype    = '"type": "%s", '    % message_type if message_type else 'default'

		return \
			'{ '\
			'"exabgp": "%s", '\
			'"time": %s, ' \
			'%s%s%s%s%s%s%s%s ' \
			'}' % (
				self.version,
				self.time(time.time()),
				peer,
				pid,
				ppid,
				counter,
				mtype,
				header,
				body,
				content
			)
Beispiel #5
0
	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))
Beispiel #6
0
    def __init__(self, code, subcode, data=b'', parse_data=True):
        self.code = code
        self.subcode = subcode

        if not parse_data:
            self.data = data
            return

        if not (code, subcode) in [(6, 2), (6, 4)]:
            self.data = data if not len([_ for _ in str(data) if _ not in string.printable]) else hexbytes(data)
            return

        if len(data) == 0:
            # shutdown without shutdown communication (the old fashioned way)
            self.data = b''
            return

        # draft-ietf-idr-shutdown or the peer was using 6,2 with data

        shutdown_length = data[0]
        data = data[1:]

        if shutdown_length == 0:
            self.data = b"empty Shutdown Communication."
            # move offset past length field
            return

        if len(data) < shutdown_length:
            self.data = b"invalid Shutdown Communication (buffer underrun) length : %i [%s]" % (
                shutdown_length,
                hexstring(data),
            )
            return

        if shutdown_length > 128:
            self.data = b"invalid Shutdown Communication (too large) length : %i [%s]" % (
                shutdown_length,
                hexstring(data),
            )
            return

        try:
            self.data = b'Shutdown Communication: "%s"' % data[:shutdown_length].decode('utf-8').replace(
                '\r', ' '
            ).replace('\n', ' ')
        except UnicodeDecodeError:
            self.data = b"invalid Shutdown Communication (invalid UTF-8) length : %i [%s]" % (
                shutdown_length,
                hexstring(data),
            )
            return

        trailer = data[shutdown_length:]
        if trailer:
            self.data += b", trailing data: " + hexstring(trailer)
Beispiel #7
0
	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))
Beispiel #8
0
	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))
Beispiel #9
0
    def unpack(cls, data, length):
        # We only support IS-IS flags for now.
        flags = cls.unpack_flags(data[0:1])
        # Parse adj weight
        weight = data[1]
        # Move pointer 4 bytes: Flags(1) + Weight(1) + Reserved(2)
        data = data[4:]
        # SID/Index/Label: according to the V and L flags, it contains
        # either:
        # *  A 3 octet local label where the 20 rightmost bits are used for
        # 	 encoding the label value.  In this case the V and L flags MUST
        # 	 be set.
        #
        # *  A 4 octet index defining the offset in the SID/Label space
        # 	 advertised by this router using the encodings defined in
        #  	 Section 3.1.  In this case V and L flags MUST be unset.
        sids = []
        raw = []
        while data:
            # Range Size: 3 octet value indicating the number of labels in
            # the range.
            if int(flags['V']) and int(flags['L']):
                sid = unpack('!L', bytes([0]) + data[:3])[0]
                data = data[3:]
                sids.append(sid)
            elif (not flags['V']) and (not flags['L']):
                sid = unpack('!I', data[:4])[0]
                data = data[4:]
                sids.append(sid)
            else:
                raw.append(hexstring(data))
                break

        return cls(flags=flags, sids=sids, weight=weight, undecoded=raw)
Beispiel #10
0
 def unpack_message(cls, data, negotiated):  # pylint: disable=W0613
     # This can not happen at decode time as we check the length of the KEEPALIVE message
     # But could happen when calling the function programmatically
     if data:
         raise Notify('Keepalive can not have any payload but contains %s',
                      hexstring(data))
     return cls()
Beispiel #11
0
	def notification (self, neighbor, direction, message, header, body):
		return self._header(self._neighbor(neighbor,direction,self._kv({
			'notification': '{ %s } ' % self._kv({
				'code':    message.code,
				'subcode': message.subcode,
				'data':    hexstring(message.data),
			})
		})),header,body,neighbor,message_type='notification')
Beispiel #12
0
	def notification (self, neighbor, direction, message, negotiated, header, body):
		return self._header(self._neighbor(neighbor,direction,self._kv({
			'notification': '{ %s } ' % self._kv({
				'code':    message.code,
				'subcode': message.subcode,
				'data':    hexstring(message.data),
			})
		})),header,body,neighbor,message_type='notification')
Beispiel #13
0
 def notification(self, neighbor, direction, message, negotiated, header, body):
     return 'neighbor %s %s notification code %d subcode %d data %s%s\n' % (
         neighbor['peer-address'],
         direction,
         message.code,
         message.subcode,
         hexstring(message.data),
         self._header_body(header, body),
     )
Beispiel #14
0
	def notification (self, neighbor, direction, message, negotiated, header, body):
		return 'neighbor %s %s notification code %d subcode %d data %s%s\n' % (
			neighbor.peer_address,
			direction,
			message.code,
			message.subcode,
			hexstring(message.data),
			self._header_body(header,body)
		)
Beispiel #15
0
	def _str (self):
		t,c1,c2,c3 = unpack('!HHHH',self.rd)
		if t == 0:
			rd = '%d:%d' % (c1,(c2 << 16)+c3)
		elif t == 1:
			rd = '%d.%d.%d.%d:%d' % (c1 >> 8,c1 & 0xFF,c2 >> 8,c2 & 0xFF,c3)
		elif t == 2:
			rd = '%d:%d' % ((c1 << 16) + c2,c3)
		else:
			rd = hexstring(self.rd)
		return rd
Beispiel #16
0
 def _str(self):
     t, c1, c2, c3 = unpack('!HHHH', self.rd)
     if t == 0:
         rd = '%d:%d' % (c1, (c2 << 16) + c3)
     elif t == 1:
         rd = '%d.%d.%d.%d:%d' % (c1 >> 8, c1 & 0xFF, c2 >> 8, c2 & 0xFF, c3)
     elif t == 2:
         rd = '%d:%d' % ((c1 << 16) + c2, c3)
     else:
         rd = hexstring(self.rd)
     return rd
Beispiel #17
0
	def __init__ (self, code, subcode, data=b'', parse_data=True):
		self.code = code
		self.subcode = subcode

		if not parse_data:
			self.data = data
			return

		if not (code, subcode) in [(6, 2), (6, 4)]:
			self.data = data if not len([_ for _ in str(data) if _ not in string.printable]) else hexbytes(data)
			return

		if len(data) == 0:
			# shutdown without shutdown communication (the old fashioned way)
			self.data = b''
			return

		# 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:
			self.data = b"empty Shutdown Communication."
			# move offset past length field
			return

		if len(data) < shutdown_length:
			self.data = b"invalid Shutdown Communication (buffer underrun) length : %i [%s]" % (shutdown_length, hexstring(data))
			return

		if shutdown_length > 128:
			self.data = b"invalid Shutdown Communication (too large) length : %i [%s]" % (shutdown_length, hexstring(data))
			return

		try:
			self.data = b'Shutdown Communication: "%s"' % \
				data[:shutdown_length].decode('utf-8').replace('\r',' ').replace('\n',' ')
		except UnicodeDecodeError:
			self.data = b"invalid Shutdown Communication (invalid UTF-8) length : %i [%s]" % (shutdown_length, hexstring(data))
			return

		trailer = data[shutdown_length:]
		if trailer:
			self.data += b", trailing data: " + hexstring(trailer)
Beispiel #18
0
    def unpack(cls, data, length):
        # We only support IS-IS flags for now.
        flags = LsGenericFlags.unpack(data[0:1], LsGenericFlags.ISIS_SR_FLAGS)
        #
        # Parse Algorithm
        sr_algo = six.indexbytes(data, 1)
        # Move pointer 4 bytes: Flags(1) + Algorithm(1) + Reserved(2)
        data = data[4:]
        # SID/Index/Label: according to the V and L flags, it contains
        # either:
        # *  A 3 octet local label where the 20 rightmost bits are used for
        #	 encoding the label value.  In this case the V and L flags MUST
        #	 be set.
        #
        # *  A 4 octet index defining the offset in the SID/Label space
        # 	 advertised by this router using the encodings defined in
        #  	 Section 3.1.  In this case V and L flags MUST be unset.
        sids = []
        raw = []
        while data:
            if flags.flags['V'] and flags.flags['L']:
                b = BitArray(bytes=data[:3])
                sid = b.unpack('uintbe:24')[0]
                data = data[3:]
                sids.append(sid)
            elif (not flags.flags['V']) and \
             (not flags.flags['L']):
                if len(data) != 4:
                    # Cisco IOS XR Software, Version 6.1.1.19I is not
                    # correctly setting the flags
                    raise Notify(
                        3, 5,
                        "SID/Label size doesn't match V and L flag state")
                sid = unpack('!I', data[:4])[0]
                data = data[4:]
                sids.append(sid)
            else:
                raw.append(hexstring(data))
                break

        return cls(flags=flags, sids=sids, sr_algo=sr_algo, undecoded=raw)
Beispiel #19
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')
Beispiel #20
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')
Beispiel #21
0
 def json(self, compact=None):
     return '"attribute-not-implemented-%s": "%s"' % (self.code,
                                                      hexstring(self.rep))
Beispiel #22
0
 def json(self):
     return '{ "id": %d, "flag": %d, "payload": "%s"}' % (
         self.ID, self.FLAG, hexstring(self.data))
Beispiel #23
0
	def json (self):
		return '{ "id": %d, "flag": %d, "payload": "%s"}' % (self.ID,self.FLAG,hexstring(self.data))
Beispiel #24
0
 def json(self):
     merged = ', '.join(['"{}"'.format(hexstring(_)) for _ in self.content])
     return '"generic-lsid-{}": [{}]'.format(self.TLV, merged)