Ejemplo n.º 1
0
	def pack (self):
		rs = []
		for k,capabilities in six.iteritems(self):
			for capability in capabilities.extract():
				rs.append(concat_bytes(character(k),character(len(capability)),capability))
		parameters = concat_bytes_i(concat_bytes(character(2),character(len(r)),r) for r in rs)
		return concat_bytes(character(len(parameters)),parameters)
Ejemplo n.º 2
0
	def _segment (self, seg_type, values, asn4):
		length = len(values)
		if length:
			if length > 255:
				return self._segment(seg_type,values[:255],asn4) + self._segment(seg_type,values[255:],asn4)
			return concat_bytes(character(seg_type),character(len(values)),concat_bytes_i(v.pack(asn4) for v in values))
		return b""
Ejemplo n.º 3
0
	def pack (self):
		rs = []
		for k,capabilities in six.iteritems(self):
			for capability in capabilities.extract():
				rs.append(concat_bytes(character(k),character(len(capability)),capability))
		parameters = concat_bytes_i(concat_bytes(character(2),character(len(r)),r) for r in rs)
		return concat_bytes(character(len(parameters)),parameters)
Ejemplo n.º 4
0
	def packed_attributes (self, negotiated, maximum=Negotiated.FREE_SIZE):
		if not self.nlris:
			return

		# addpath = negotiated.addpath.send(self.afi,self.safi)
		# nexthopself = negotiated.nexthopself(self.afi)
		mpnlri = {}
		for nlri in self.nlris:
			if nlri.family() != self.family():  # nlri is not part of specified family
				continue
			if nlri.nexthop is NoNextHop:
				# EOR and Flow may not have any next_hop
				nexthop = b''
			else:
				_,rd_size = Family.size.get(self.family(),(0,0))
				nh_rd = character(0)*rd_size if rd_size else b''
				nexthop = nh_rd + nlri.nexthop.ton(negotiated,nlri.afi)

			# mpunli[nexthop] = nlri
			mpnlri.setdefault(nexthop,[]).append(nlri.pack(negotiated))

		for nexthop,nlris in six.iteritems(mpnlri):
			payload = concat_bytes(self.afi.pack(), self.safi.pack(), character(len(nexthop)), nexthop, character(0))
			header_length = len(payload)
			for nlri in nlris:
				if self._len(payload + nlri) > maximum:
					if len(payload) == header_length or len(payload) > maximum:
						raise Notify(6, 0, 'attributes size is so large we can not even pack on MPRNLRI')
					yield self._attribute(payload)
					payload = concat_bytes(self.afi.pack(), self.safi.pack(), character(len(nexthop)), nexthop, character(0), nlri)
					continue
				payload  = concat_bytes(payload, nlri)
			if len(payload) == header_length or len(payload) > maximum:
				raise Notify(6, 0, 'attributes size is so large we can not even pack on MPRNLRI')
			yield self._attribute(payload)
Ejemplo n.º 5
0
    def pack_nlri(self, negotiated=None):
        ordered_rules = []
        # the order is a RFC requirement
        for ID in sorted(self.rules.keys()):
            rules = self.rules[ID]
            # for each component get all the operation to do
            # the format use does not prevent two opposing rules meaning that no packet can ever match
            for rule in rules:
                rule.operations &= (CommonOperator.EOL ^ 0xFF)
            rules[-1].operations |= CommonOperator.EOL
            # and add it to the last rule
            if ID not in (FlowDestination.ID, FlowSource.ID):
                ordered_rules.append(character(ID))
            ordered_rules.append(concat_bytes_i(rule.pack() for rule in rules))

        components = self.rd.pack() + concat_bytes_i(ordered_rules)

        lc = len(components)
        if lc < 0xF0:
            return concat_bytes(character(lc), components)
        if lc < 0x0FFF:
            return concat_bytes(pack('!H', lc | 0xF000), components)
        raise Notify(
            3, 0,
            "my administrator attempted to announce a Flow Spec rule larger than encoding allows, protecting the innocent the only way I can"
        )
Ejemplo n.º 6
0
 def extract(self):
     rs = [
         character(0),
     ]
     for v in self:
         rs.append(character(v))
     return rs
Ejemplo n.º 7
0
	def extract (self):
		return [concat_bytes(
			character(len(self.host_name)),
			self.host_name,
			character(len(self.domain_name)),
			self.domain_name,
		)]
Ejemplo n.º 8
0
	def __init__ (self, packed=None, integer=None, ip=None):
		if packed:
			self.path_info = packed
		elif ip:
			self.path_info = concat_bytes_i(character(int(_)) for _ in ip.split('.'))
		elif integer:
			self.path_info = concat_bytes_i(character((integer >> offset) & 0xff) for offset in [24,16,8,0])
		else:
			self.path_info = b''
Ejemplo n.º 9
0
	def __init__ (self, packed=None, integer=None, ip=None):
		if packed:
			self.path_info = packed
		elif ip:
			self.path_info = concat_bytes_i(character(int(_)) for _ in ip.split('.'))
		elif integer:
			self.path_info = concat_bytes_i(character((integer >> offset) & 0xff) for offset in [24,16,8,0])
		else:
			self.path_info = b''
Ejemplo n.º 10
0
 def extract(self):
     return [
         concat_bytes(
             character(len(self.host_name)),
             self.host_name,
             character(len(self.domain_name)),
             self.domain_name,
         )
     ]
Ejemplo n.º 11
0
	def pack (self, negotiated=None):
		flag = self.FLAG
		length = len(self.data)
		if length > 0xFF:
			flag |= Attribute.Flag.EXTENDED_LENGTH
		if flag & Attribute.Flag.EXTENDED_LENGTH:
			len_value = pack('!H',length)
		else:
			len_value = character(length)
		return concat_bytes(character(flag),character(self.ID),len_value,self.data)
Ejemplo n.º 12
0
 def _segment(self, seg_type, values, asn4):
     length = len(values)
     if length:
         if length > 255:
             return self._segment(seg_type, values[:255],
                                  asn4) + self._segment(
                                      seg_type, values[255:], asn4)
         return concat_bytes(character(seg_type), character(len(values)),
                             concat_bytes_i(v.pack(asn4) for v in values))
     return b""
Ejemplo n.º 13
0
def route_distinguisher(tokeniser):
    data = tokeniser()

    separator = data.find(':')
    if separator > 0:
        prefix = data[:separator]
        suffix = int(data[separator + 1:])

    if '.' in prefix:
        data = [character(0), character(1)]
        data.extend([character(int(_)) for _ in prefix.split('.')])
        data.extend([character(suffix >> 8), character(suffix & 0xFF)])
        rtd = concat_bytes_i(data)
    else:
        number = int(prefix)
        if number < pow(2, 16) and suffix < pow(2, 32):
            rtd = character(0) + character(0) + pack('!H', number) + pack(
                '!L', suffix)
        elif number < pow(2, 32) and suffix < pow(2, 16):
            rtd = character(0) + character(2) + pack('!L', number) + pack(
                '!H', suffix)
        else:
            raise ValueError('invalid route-distinguisher %s' % data)

    return RouteDistinguisher(rtd)
Ejemplo n.º 14
0
class ESI(object):
    DEFAULT = concat_bytes_i(character(0) for _ in range(0, 10))
    MAX = concat_bytes_i(character(0xFF) for _ in range(0, 10))

    __slots__ = ['esi']

    def __init__(self, esi=None):
        self.esi = self.DEFAULT if esi is None else esi
        if len(self.esi) != 10:
            raise Exception("incorrect ESI, len %d instead of 10" % len(esi))

    def __eq__(self, other):
        return self.esi == other.esi

    def __neq__(self, other):
        return self.esi != other.esi

    def __lt__(self, other):
        raise RuntimeError('comparing ESI for ordering does not make sense')

    def __le__(self, other):
        raise RuntimeError('comparing ESI for ordering does not make sense')

    def __gt__(self, other):
        raise RuntimeError('comparing ESI for ordering does not make sense')

    def __ge__(self, other):
        raise RuntimeError('comparing ESI for ordering does not make sense')

    def __str__(self):
        if self.esi == self.DEFAULT:
            return "-"
        return ":".join('%02x' % ordinal(_) for _ in self.esi)

    def __repr__(self):
        return self.__str__()

    def pack(self):
        return self.esi

    def __len__(self):
        return 10

    def __hash__(self):
        return hash(self.esi)

    @classmethod
    def unpack(cls, data):
        return cls(data[:10])

    def json(self, compact=None):
        return '"esi": "%s"' % str(self)
Ejemplo n.º 15
0
 def _attribute(self, value):
     flag = self.FLAG
     if flag & Attribute.Flag.OPTIONAL and not value:
         return b''
     length = len(value)
     if length > 0xFF:
         flag |= Attribute.Flag.EXTENDED_LENGTH
     if flag & Attribute.Flag.EXTENDED_LENGTH:
         len_value = pack('!H', length)
     else:
         len_value = character(length)
     return concat_bytes(character(flag), character(self.ID), len_value,
                         value)
Ejemplo n.º 16
0
def attribute(tokeniser):
    start = tokeniser()
    if start != '[':
        raise ValueError('invalid attribute, does not starts with [')

    code = tokeniser().lower()
    if not code.startswith('0x'):
        raise ValueError('invalid attribute, code is not 0x hexadecimal')
    try:
        code = int(code, 16)
    except ValueError:
        raise ValueError('invalid attribute, code is not 0x hexadecimal')

    flag = tokeniser().lower()
    if not flag.startswith('0x'):
        raise ValueError('invalid attribute, flag is not 0x hexadecimal')
    try:
        flag = int(flag, 16)
    except ValueError:
        raise ValueError('invalid attribute, flag is not 0x hexadecimal')

    data = tokeniser().lower()
    if not data.startswith('0x'):
        raise ValueError('invalid attribute, data is not 0x hexadecimal')
    if len(data) % 2:
        raise ValueError('invalid attribute, data is not 0x hexadecimal')
    data = concat_bytes_i(
        character(int(data[_:_ + 2], 16)) for _ in range(2, len(data), 2))

    end = tokeniser()
    if end != ']':
        raise ValueError('invalid attribute, does not ends with ]')

    return GenericAttribute(code, flag, data)
Ejemplo n.º 17
0
def unescape (string):
	start = 0
	while start < len(string):
		pos = string.find('\\', start)
		if pos == -1:
			yield string[start:]
			break
		yield string[start:pos]
		pos += 1
		esc = string[pos]
		if esc == 'b':
			yield '\b'
		elif esc == 'f':
			yield '\f'
		elif esc == 'n':
			yield '\n'
		elif esc == 'r':
			yield '\r'
		elif esc == 't':
			yield '\t'
		elif esc == 'u':
			yield character(int(string[pos + 1:pos + 5], 16))
			pos += 4
		else:
			yield esc
		start = pos + 1
Ejemplo n.º 18
0
def attribute (tokeniser):
	start = tokeniser()
	if start != '[':
		raise ValueError('invalid attribute, does not starts with [')

	code = tokeniser().lower()
	if not code.startswith('0x'):
		raise ValueError('invalid attribute, code is not 0x hexadecimal')
	try:
		code = int(code,16)
	except ValueError:
		raise ValueError('invalid attribute, code is not 0x hexadecimal')

	flag = tokeniser().lower()
	if not flag.startswith('0x'):
		raise ValueError('invalid attribute, flag is not 0x hexadecimal')
	try:
		flag = int(flag,16)
	except ValueError:
		raise ValueError('invalid attribute, flag is not 0x hexadecimal')

	data = tokeniser().lower()
	if not data.startswith('0x'):
		raise ValueError('invalid attribute, data is not 0x hexadecimal')
	if len(data) % 2:
		raise ValueError('invalid attribute, data is not 0x hexadecimal')
	data = concat_bytes_i(character(int(data[_:_+2],16)) for _ in range(2,len(data),2))

	end = tokeniser()
	if end != ']':
		raise ValueError('invalid attribute, does not ends with ]')

	return GenericAttribute(code,flag,data)
Ejemplo n.º 19
0
    def _signature_segment (self, asns=None, skis=None):
        sig_segment = []

        if not skis or not asns:
          skis = copy.deepcopy(self.all_skis)
          #skis.reverse()

        # split SKI string into 2 letters
        step = 2
        #for ski in reversed(skis):
        for ski in skis:
          #self.ski_str = self.negotiated.neighbor.ski[0]
          self.ski_str = ski
          splitSKI = [ski[i:i+step] for i in range(0, len(ski), step) ]

          # convert hexstring into integer
          result = [ character( int(splitSKI[i], 16)) for i in range (0, len(splitSKI))]
          sig_segment.extend(result)

          # processing signatures
          # dict-asn-ski.keys(): list of keys, dict.values(): list of values  list.index(n): index number
          if self.dict_asn_ski and ski in self.dict_asn_ski.values() :
            host_asn = list(self.dict_asn_ski.keys())[list(self.dict_asn_ski.values()).index(ski)]
          else :
            # TODO: need default action
            host_asn = None

          sig_segment_value = self._signature(host_asn, ski)
          if not sig_segment_value :
              return None

          sig_segment.append(sig_segment_value)
          self.signature_block_len += self.SIG_LEN + self.SKI_LEN
        return sig_segment
Ejemplo n.º 20
0
def unescape(string):
    start = 0
    while start < len(string):
        pos = string.find('\\', start)
        if pos == -1:
            yield string[start:]
            break
        yield string[start:pos]
        pos += 1
        esc = string[pos]
        if esc == 'b':
            yield '\b'
        elif esc == 'f':
            yield '\f'
        elif esc == 'n':
            yield '\n'
        elif esc == 'r':
            yield '\r'
        elif esc == 't':
            yield '\t'
        elif esc == 'u':
            yield character(int(string[pos + 1:pos + 5], 16))
            pos += 4
        else:
            yield esc
        start = pos + 1
Ejemplo n.º 21
0
    def test_nlri(self):
        components = {
            'destination': Flow4Destination(IPv4.pton("192.0.2.0"), 24),
            'source': Flow4Source(IPv4.pton("10.1.2.0"), 24),
            'anyport_1': FlowAnyPort(NumericOperator.EQ | NumericOperator.GT,
                                     25),
            'anyport_2': FlowAnyPort(NumericOperator.EQ | NumericOperator.LT,
                                     80),
        }
        messages = {
            'destination': [0x01, 0x18, 0xc0, 0x00, 0x02],
            'source': [0x02, 0x18, 0x0a, 0x01, 0x02],
            'anyport_1': [0x04, 0x43, 0x19],
            'anyport_2': [0x85, 0x50],
        }

        flow = Flow()
        message = b""
        for key in ['destination', 'source', 'anyport_1', 'anyport_2']:
            flow.add(components[key])
            message += data_from_body(messages[key])
        message = character(len(message)) + message
        # policy.add(to_FlowAction(65000,False,False))
        flow = flow.pack()
        if message[0] != flow[0]:
            self.fail('size mismatch %s %s\n' %
                      (ordinal(flow[0]), ordinal(message[0])))
        if len(flow) != ordinal(flow[0]) + 1:
            self.fail('invalid size for message')
Ejemplo n.º 22
0
 def pack(self, negotiated=None):
     addpath = self.path_info.pack(
     ) if negotiated and negotiated.addpath.send(self.afi,
                                                 self.safi) else b''
     mask = character(
         len(self.labels) * 8 + len(self.rd) * 8 + self.cidr.mask)
     return addpath + mask + self.labels.pack() + self.rd.pack(
     ) + self.cidr.pack_ip()
Ejemplo n.º 23
0
class EOR(Message):
    ID = Message.CODE.UPDATE
    TYPE = character(Message.CODE.UPDATE)

    class NLRI(_NLRI):
        PREFIX = b'\x00\x00\x00\x07\x90\x0F\x00\x03'
        MP_LENGTH = len(PREFIX) + 1 + 2  # len(AFI) and len(SAFI)
        EOR = True

        nexthop = None

        def __init__(self, afi, safi, action):
            _NLRI.__init__(self, afi, safi, action)
            self.action = action
            self.afi = afi
            self.safi = safi

        def pack_nlri(self, negotiated=None):
            if self.afi == AFI.ipv4 and self.safi == SAFI.unicast:
                return b'\x00\x00\x00\x00'
            return self.PREFIX + self.afi.pack() + self.safi.pack()

        def __repr__(self):
            return self.extensive()

        def extensive(self):
            return 'eor %ld/%ld (%s %s)' % (long(self.afi), long(
                self.safi), self.afi, self.safi)

        def json(self, announced=True, compact=None):
            return '"eor": { "afi" : "%s", "safi" : "%s" }' % (self.afi,
                                                               self.safi)

        def __len__(self):
            if self.afi == AFI.ipv4 and self.safi == SAFI.unicast:
                # May not have been the size read on the wire if MP was used for IPv4 unicast
                return 4
            else:
                return self.MP_LENGTH

    def __init__(self, afi, safi, action=None):
        Message.__init__(self)
        self.nlris = [
            EOR.NLRI(afi, safi, action),
        ]
        self.attributes = Attributes()

    def message(self, negotiated=None):
        return self._message(self.nlris[0].pack())

    def __repr__(self):
        return 'EOR'

    @classmethod
    def unpack_message(cls, data, negotiated):
        header_length = len(EOR.NLRI.PREFIX)
        return cls(AFI.unpack(data[header_length:header_length + 2]),
                   SAFI.unpack(data[header_length + 2]))
Ejemplo n.º 24
0
    def test101_EVPNHashEqual_somefieldsvary(self):
        '''
        Two EVPN MAC NLRIs differing by their ESI or label or RD,
        or nexthop, but otherwise identical should hash to the same value,
        and be equal
        '''

        nlri0 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([42], True), IP.create("1.1.1.1"))

        # ESI
        nlri1 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(b''.join(character(1) for _ in range(0, 10))),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([42], True), IP.create("1.1.1.1"))

        # label
        nlri2 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([4444], True), IP.create("1.1.1.1"))

        # IP: different IPs, but same MACs: different route
        nlri3 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([42], True), IP.create("2.2.2.2"))

        # with a next hop...
        nlri4 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([42], True), IP.create("1.1.1.1"),
                        IP.pton("10.10.10.10"))
        nlri5 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([42], True), IP.create("1.1.1.1"),
                        IP.pton("11.11.11.11"))

        self.assertEqual(hash(nlri0), hash(nlri1))
        self.assertEqual(hash(nlri0), hash(nlri2))
        self.assertEqual(hash(nlri0), hash(nlri4))
        self.assertEqual(nlri0, nlri1)
        self.assertEqual(nlri0, nlri2)
        self.assertEqual(nlri0, nlri4)
        self.assertEqual(nlri1, nlri2)
        self.assertEqual(nlri1, nlri4)
        self.assertEqual(nlri2, nlri4)
        self.assertEqual(nlri4, nlri5)

        self.assertNotEqual(hash(nlri0), hash(nlri3))
        self.assertNotEqual(nlri0, nlri3)
        self.assertNotEqual(nlri1, nlri3)
        self.assertNotEqual(nlri2, nlri3)
        self.assertNotEqual(nlri3, nlri4)
Ejemplo n.º 25
0
    def unpack_nlri(cls, afi, safi, bgp, action, addpath):
        nlri = cls(afi, safi, action)

        if addpath:
            nlri.path_info = PathInfo(bgp[:4])
            bgp = bgp[4:]

        mask = ordinal(bgp[0])
        bgp = bgp[1:]

        _, rd_size = Family.size.get((afi, safi), (0, 0))
        rd_mask = rd_size * 8

        if safi.has_label():
            labels = []
            while mask - rd_mask >= 24:
                label = int(unpack('!L', character(0) + bgp[:3])[0])
                bgp = bgp[3:]
                mask -= 24  # 3 bytes
                # The last 4 bits are the bottom of Stack
                # The last bit is set for the last label
                labels.append(label >> 4)
                # This is a route withdrawal
                if label == 0x800000 and action == IN.WITHDRAWN:
                    break
                # This is a next-hop
                if label == 0x000000:
                    break
                if label & 1:
                    break
            nlri.labels = Labels(labels)

        if rd_size:
            mask -= rd_mask  # the route distinguisher
            rd = bgp[:rd_size]
            bgp = bgp[rd_size:]
            nlri.rd = RouteDistinguisher(rd)

        if mask < 0:
            raise Notify(3, 10, 'invalid length in NLRI prefix')

        if not bgp and mask:
            raise Notify(
                3, 10,
                'not enough data for the mask provided to decode the NLRI')

        size = CIDR.size(mask)

        if len(bgp) < size:
            raise Notify(
                3, 10,
                'could not decode route with AFI %d and SAFI %d' % (afi, safi))

        network, bgp = bgp[:size], bgp[size:]

        nlri.cidr = CIDR(network + padding(IP.length(afi) - size), mask)

        return nlri, bgp
Ejemplo n.º 26
0
    def _pack(self, packed=None):
        if self._packed:
            return self._packed

        if packed:
            self._packed = packed
            return packed

        self._packed = concat_bytes(
            self.rd.pack(),
            self.esi.pack(),
            self.etag.pack(),
            character(self.maclen),  # only 48 supported by the draft
            self.mac.pack(),
            character(len(self.ip) * 8 if self.ip else 0),
            self.ip.pack() if self.ip else b'',
            self.label.pack())
        return self._packed
Ejemplo n.º 27
0
 def extract(self):
     restart = pack('!H', ((self.restart_flag << 12) |
                           (self.restart_time & Graceful.TIME_MASK)))
     families = [(afi.pack(), safi.pack(), character(self[(afi, safi)]))
                 for (afi, safi) in self.keys()]
     sfamilies = concat_bytes_i(
         concat_bytes(pafi, psafi, family)
         for (pafi, psafi, family) in families)
     return [concat_bytes(restart, sfamilies)]
Ejemplo n.º 28
0
	def unpack (cls, data):
		labels = []
		while len(data):
			label = unpack('!L',character(0)+data[:3])[0]
			data = data[3:]
			labels.append(label >> 4)
			if label & 0x001:
				break
		return cls(labels)
Ejemplo n.º 29
0
	def _pack (self, packed=None):
		if self._packed:
			return self._packed

		if packed:
			self._packed = packed
			return packed

		self._packed = concat_bytes(
			self.rd.pack(),
			self.esi.pack(),
			self.etag.pack(),
			character(self.maclen),  # only 48 supported by the draft
			self.mac.pack(),
			character(len(self.ip)*8 if self.ip else 0),
			self.ip.pack() if self.ip else b'',
			self.label.pack()
		)
		return self._packed
Ejemplo n.º 30
0
	def unpack_nlri (cls, afi, safi, bgp, action, addpath):
		nlri = cls(afi,safi,action)

		if addpath:
			nlri.path_info = PathInfo(bgp[:4])
			bgp = bgp[4:]

		mask = ordinal(bgp[0])
		bgp = bgp[1:]

		_, rd_size = Family.size.get((afi, safi), (0, 0))
		rd_mask = rd_size * 8

		if safi.has_label():
			labels = []
			while mask - rd_mask >= 24:
				label = int(unpack('!L',character(0) + bgp[:3])[0])
				bgp = bgp[3:]
				mask -= 24  	# 3 bytes
				# The last 4 bits are the bottom of Stack
				# The last bit is set for the last label
				labels.append(label >> 4)
				# This is a route withdrawal
				if label == 0x800000 and action == IN.WITHDRAWN:
					break
				# This is a next-hop
				if label == 0x000000:
					break
				if label & 1:
					break
			nlri.labels = Labels(labels)


		if rd_size:
			mask -= rd_mask  # the route distinguisher
			rd = bgp[:rd_size]
			bgp = bgp[rd_size:]
			nlri.rd = RouteDistinguisher(rd)

		if mask < 0:
			raise Notify(3,10,'invalid length in NLRI prefix')

		if not bgp and mask:
			raise Notify(3,10,'not enough data for the mask provided to decode the NLRI')

		size = CIDR.size(mask)

		if len(bgp) < size:
			raise Notify(3,10,'could not decode route with AFI %d and SAFI %d' % (afi,safi))

		network,bgp = bgp[:size],bgp[size:]

		nlri.cidr = CIDR(network + padding(IP.length(afi)-size),mask)

		return nlri,bgp
Ejemplo n.º 31
0
    def _pack(self, packed=None):
        if self._packed:
            return self._packed

        if packed:
            self._packed = packed
            return packed

        self._packed = concat_bytes(self.rd.pack(), self.etag.pack(),
                                    character(len(self.ip) * 8),
                                    self.ip.pack())
        return self._packed
Ejemplo n.º 32
0
def destination(tokeniser):
    data = tokeniser()
    if data.count('.') == 3 and data.count(':') == 0:
        ip, netmask = data.split('/')
        raw = concat_bytes_i(character(int(_)) for _ in ip.split('.'))
        yield Flow4Destination(raw, int(netmask))
    elif data.count('/') == 1:
        ip, netmask = data.split('/')
        offset = 0
        yield Flow6Destination(IP.pton(ip), int(netmask), int(offset))
    else:
        ip, netmask, offset = data.split('/')
        yield Flow6Destination(IP.pton(ip), int(netmask), int(offset))
Ejemplo n.º 33
0
class NOP (Message):
	ID = Message.CODE.NOP
	TYPE = character(Message.CODE.NOP)

	def message (self,negotiated=None):
		raise RuntimeError('NOP messages can not be sent on the wire')

	def __str__ (self):
		return "NOP"

	@classmethod
	def unpack_message (cls, data, negotiated):  # pylint: disable=W0613
		return NOP()
Ejemplo n.º 34
0
    def _pack(self, packed=None):
        if self._packed:
            return self._packed

        if packed:
            self._packed = packed
            return packed

        self._packed = concat_bytes(
            self.rd.pack(), self.esi.pack(),
            character(len(self.ip) * 8 if self.ip else 0),
            self.ip.pack() if self.ip else b'')
        return self._packed
Ejemplo n.º 35
0
def destination (tokeniser):
	data = tokeniser()
	if data.count('.') == 3 and data.count(':') == 0:
		ip,netmask = data.split('/')
		raw = concat_bytes_i(character(int(_)) for _ in ip.split('.'))
		yield Flow4Destination(raw,int(netmask))
	elif data.count('/') == 1:
		ip,netmask = data.split('/')
		offset = 0
		yield Flow6Destination(IP.pton(ip),int(netmask),int(offset))
	else:
		ip,netmask,offset = data.split('/')
		yield Flow6Destination(IP.pton(ip),int(netmask),int(offset))
Ejemplo n.º 36
0
class RouteRefresh(Message):
    ID = Message.CODE.ROUTE_REFRESH
    TYPE = character(Message.CODE.ROUTE_REFRESH)

    request = 0
    start = 1
    end = 2

    def __init__(self, afi, safi, reserved=0):
        self.afi = AFI.create(afi)
        self.safi = SAFI.create(safi)
        self.reserved = Reserved(reserved)

    def message(self, negotiated=None):
        return self._message(
            concat_bytes(self.afi.pack(), character(self.reserved),
                         self.safi.pack()))

    def __str__(self):
        return "REFRESH"

    def extensive(self):
        return 'route refresh %s/%d/%s' % (self.afi, self.reserved, self.safi)

    # XXX: Check how we get this data into the RR
    def families(self):
        return self._families[:]

    @classmethod
    def unpack_message(cls, data, _):
        try:
            afi, reserved, safi = unpack('!HBB', data)
        except error:
            raise Notify(7, 1, 'invalid route-refresh message')
        if reserved not in (0, 1, 2):
            raise Notify(7, 2, 'invalid route-refresh message subtype')
        return RouteRefresh(afi, safi, reserved)

    def __eq__(self, other):
        if not isinstance(other, RouteRefresh):
            return False
        if self.afi != other.afi:
            return False
        if self.safi != other.safi:
            return False
        if self.reserved != other.reserved:
            return False
        return True

    def __ne__(self, other):
        return not self.__eq__(other)
Ejemplo n.º 37
0
	def fromElements (cls, prefix, suffix):
		try:
			if '.' in prefix:
				data = [character(0),character(1)]
				data.extend([character(int(_)) for _ in prefix.split('.')])
				data.extend([character(suffix >> 8),character(suffix & 0xFF)])
				distinguisher = concat_bytes_i(data)
			else:
				number = int(prefix)
				if number < pow(2,16) and suffix < pow(2,32):
					distinguisher = character(0) + character(0) + pack('!H',number) + pack('!L',suffix)
				elif number < pow(2,32) and suffix < pow(2,16):
					distinguisher = character(0) + character(2) + pack('!L',number) + pack('!H',suffix)
				else:
					raise ValueError('invalid route-distinguisher %s' % number)

			return cls(distinguisher)
		except ValueError:
			raise ValueError('invalid route-distinguisher %s:%s' % (prefix,suffix))
Ejemplo n.º 38
0
Archivo: rd.py Proyecto: aabdnn/exabgp
	def fromElements (cls, prefix, suffix):
		try:
			if '.' in prefix:
				data = [character(0),character(1)]
				data.extend([character(int(_)) for _ in prefix.split('.')])
				data.extend([character(suffix >> 8),character(suffix & 0xFF)])
				distinguisher = concat_bytes_i(data)
			else:
				number = int(prefix)
				if number < pow(2,16) and suffix < pow(2,32):
					distinguisher = character(0) + character(0) + pack('!H',number) + pack('!L',suffix)
				elif number < pow(2,32) and suffix < pow(2,16):
					distinguisher = character(0) + character(2) + pack('!L',number) + pack('!H',suffix)
				else:
					raise ValueError('invalid route-distinguisher %s' % number)

			return cls(distinguisher)
		except ValueError:
			raise ValueError('invalid route-distinguisher %s:%s' % (prefix,suffix))
Ejemplo n.º 39
0
	def pack_nlri (self, negotiated=None):
		ordered_rules = []
		# the order is a RFC requirement
		for ID in sorted(self.rules.keys()):
			rules = self.rules[ID]
			# for each component get all the operation to do
			# the format use does not prevent two opposing rules meaning that no packet can ever match
			for rule in rules:
				rule.operations &= (CommonOperator.EOL ^ 0xFF)
			rules[-1].operations |= CommonOperator.EOL
			# and add it to the last rule
			if ID not in (FlowDestination.ID,FlowSource.ID):
				ordered_rules.append(character(ID))
			ordered_rules.append(concat_bytes_i(rule.pack() for rule in rules))

		components = self.rd.pack() + concat_bytes_i(ordered_rules)

		lc = len(components)
		if lc < 0xF0:
			return concat_bytes(character(lc),components)
		if lc < 0x0FFF:
			return concat_bytes(pack('!H',lc | 0xF000),components)
		raise Notify(3,0,"my administrator attempted to announce a Flow Spec rule larger than encoding allows, protecting the innocent the only way I can")
Ejemplo n.º 40
0
	def _pack (self, packed=None):
		if self._packed:
			return self._packed

		if packed:
			self._packed = packed
			return packed

		self._packed = concat_bytes(
			self.rd.pack(),
			self.etag.pack(),
			character(len(self.ip)*8),
			self.ip.pack()
		)
		return self._packed
Ejemplo n.º 41
0
	def _pack (self, packed=None):
		if self._packed:
			return self._packed

		if packed:
			self._packed = packed
			return packed

		self._packed = concat_bytes(
			self.rd.pack(),
			self.esi.pack(),
			character(len(self.ip)*8 if self.ip else 0),
			self.ip.pack() if self.ip else b''
		)
		return self._packed
Ejemplo n.º 42
0
def check_message (neighbor, message):
	message = message.replace(':','')
	raw = concat_bytes_i(character(int(_,16)) for _ in (message[i*2:(i*2)+2] for i in range(len(message)//2)))

	if raw.startswith(b'\xff'*16):
		kind = ordinal(raw[18])
		# XXX: FIXME: check size
		# size = (ordinal(raw[16]) << 16) + (ordinal(raw[17]))

		if kind == 1:
			return check_open(neighbor,raw[18:])
		elif kind == 2:
			return check_update(neighbor,raw)
		elif kind == 3:
			return check_notification(raw)
	else:
		return check_update(neighbor,raw)
Ejemplo n.º 43
0
def check_message (neighbor, message):
	message = message.replace(':','')
	raw = concat_bytes_i(character(int(_,16)) for _ in (message[i*2:(i*2)+2] for i in range(len(message)//2)))

	if raw.startswith(b'\xff'*16):
		kind = ordinal(raw[18])
		# XXX: FIXME: check size
		# size = (ordinal(raw[16]) << 16) + (ordinal(raw[17]))

		if kind == 1:
			return check_open(neighbor,raw[18:])
		elif kind == 2:
			return check_update(neighbor,raw)
		elif kind == 3:
			return check_notification(raw)
	else:
		return check_update(neighbor,raw)
Ejemplo n.º 44
0
class KeepAlive (Message):
	ID = Message.CODE.KEEPALIVE
	TYPE = character(Message.CODE.KEEPALIVE)

	def message (self,negotiated=None):
		return self._message(b'')

	def __str__ (self):
		return "KEEPALIVE"

	@classmethod
	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()
Ejemplo n.º 45
0
def route_distinguisher (tokeniser):
	data = tokeniser()

	separator = data.find(':')
	if separator > 0:
		prefix = data[:separator]
		suffix = int(data[separator+1:])

	if '.' in prefix:
		data = [character(0),character(1)]
		data.extend([character(int(_)) for _ in prefix.split('.')])
		data.extend([character(suffix >> 8),character(suffix & 0xFF)])
		rtd = concat_bytes_i(data)
	else:
		number = int(prefix)
		if number < pow(2,16) and suffix < pow(2,32):
			rtd = character(0) + character(0) + pack('!H',number) + pack('!L',suffix)
		elif number < pow(2,32) and suffix < pow(2,16):
			rtd = character(0) + character(2) + pack('!L',number) + pack('!H',suffix)
		else:
			raise ValueError('invalid route-distinguisher %s' % data)

	return RouteDistinguisher(rtd)
Ejemplo n.º 46
0
	def _pack (self, packed=None):
		if self._packed:
			return self._packed

		if packed:
			self._packed = packed
			return packed

		self._packed = concat_bytes(
			self.rd.pack(),
			self.esi.pack(),
			self.etag.pack(),
			character(self.iplen),
			self.ip.pack(),
			self.gwip.pack(),
			self.label.pack(),
		)
		return self._packed
Ejemplo n.º 47
0
	def pack_nlri (self):
		return character(self.mask) + self._packed[:CIDR.size(self.mask)]
Ejemplo n.º 48
0
def pack_int (afi, integer):
	return concat_bytes_i(character((integer >> (offset * 8)) & 0xff) for offset in range(IP.length(afi)-1,-1,-1))
Ejemplo n.º 49
0
	def resetFlags(char):
		return character(ordinal(char) & ~(Attribute.Flag.TRANSITIVE | Attribute.Flag.OPTIONAL))
Ejemplo n.º 50
0
	def __init__ (self, origin, packed=None):
		self.origin = origin
		self._packed = self._attribute(packed if packed else character(origin))
Ejemplo n.º 51
0
	def from_rt(cls, route_target):
		packed = route_target.pack()
		return cls.unpack(concat_bytes(packed[0:1], character(cls.COMMUNITY_SUBTYPE), packed[2:]))
Ejemplo n.º 52
0
	def extract (self):
		restart  = pack('!H',((self.restart_flag << 12) | (self.restart_time & Graceful.TIME_MASK)))
		families = [(afi.pack(),safi.pack(),character(self[(afi,safi)])) for (afi,safi) in self.keys()]
		sfamilies = concat_bytes_i(concat_bytes(pafi,psafi,family) for (pafi,psafi,family) in families)
		return [concat_bytes(restart,sfamilies)]
Ejemplo n.º 53
0
	def pack (self):
		l,v = self.encode(self.value)
		op = self.operations | _len_to_bit(l)
		return concat_bytes(character(op),v)
Ejemplo n.º 54
0
	def encode (self, value):
		return 1,character(value)
Ejemplo n.º 55
0
	def __hash__ (self):
		return hash(character(self.mask)+self._packed)
Ejemplo n.º 56
0
	def encode (self, value):
		if value < (1 << 8):
			return 1,character(value)
		if value < (1 << 16):
			return 2,pack('!H',value)
		return 4,pack('!L',value)
Ejemplo n.º 57
0
	def pack (self, negotiated=None):
		addpath = self.path_info.pack() if negotiated and negotiated.addpath.send(self.afi,self.safi) else b''
		mask = character(len(self.labels)*8 + len(self.rd)*8 + self.cidr.mask)
		return addpath + mask + self.labels.pack() + self.rd.pack() + self.cidr.pack_ip()