Example #1
0
File: mac.py Project: abn/exabgp
	def unpack (cls, data):
		datalen = len(data)
		rd = RouteDistinguisher.unpack(data[:8])
		esi = ESI.unpack(data[8:18])
		etag = EthernetTag.unpack(data[18:22])
		maclength = ord(data[22])

		if (maclength > 48 or maclength < 0):
			raise Notify(3,5,'invalid MAC Address length in %s' % cls.NAME)
		end = 23 + 6 # MAC length MUST be 6

		mac = MACQUAL.unpack(data[23:end])

		length = ord(data[end])
		iplen = length / 8

		if datalen in [33,36]:  # No IP information (1 or 2 labels)
			iplenUnpack = 0
			if iplen != 0:
				raise Notify(3,5,"IP length is given as %d, but current MAC route has no IP information" % iplen)
		elif datalen in [37, 40]:  # Using IPv4 addresses (1 or 2 labels)
			iplenUnpack = 4
			if (iplen > 32 or iplen < 0):
				raise Notify(3,5,"IP field length is given as %d, but current MAC route is IPv4 and valus is out of range" % iplen)
		elif datalen in [49, 52]:  # Using IPv6 addresses (1 or 2 labels)
			iplenUnpack = 16
			if (iplen > 128 or iplen < 0):
				raise Notify(3,5,"IP field length is given as %d, but current MAC route is IPv6 and valus is out of range" % iplen)
		else:
			raise Notify(3,5,"Data field length is given as %d, but does not match one of the expected lengths" % datalen)

		ip = IP.unpack(data[end+1:end+1+iplenUnpack])
		label = Labels.unpack(data[end+1+iplenUnpack:end+1+iplenUnpack+3])

		return cls(rd,esi,etag,mac,maclength,label,ip,data)
Example #2
0
	def unpack (cls, exdata):
		data = exdata

		# Get the data length to understand if addresses are IPv4 or IPv6
		datalen = len(data)

		rd = RouteDistinguisher.unpack(data[:8])
		data = data[8:]

		esi = ESI.unpack(data[:10])
		data = data[10:]

		etag = EthernetTag.unpack(data[:4])
		data = data[4:]

		iplen = ord(data[0])
		data = data[1:]

		if datalen == (26 + 8):  # Using IPv4 addresses
			ip = IP.unpack(data[:4])
			data = data[4:]
			gwip = IP.unpack(data[:4])
			data = data[4:]
		elif datalen == (26 + 32):  # Using IPv6 addresses
			ip = IP.unpack(data[:16])
			data = data[16:]
			gwip = IP.unpack(data[:16])
			data = data[16:]
		else:
			raise Notify(3,5,"Data field length is given as %d, but EVPN route currently support only IPv4 or IPv6(34 or 58)" % iplen)

		label = Labels.unpack(data[:3])

		return cls(rd,esi,etag,label,ip,iplen,gwip,exdata)
Example #3
0
	def unpack (cls, exdata):
		data = exdata

		# Get the data length to understand if addresses are IPv4 or IPv6
		datalen = len(data)

		rd = RouteDistinguisher.unpack(data[:8])
		data = data[8:]

		esi = ESI.unpack(data[:10])
		data = data[10:]

		etag = EthernetTag.unpack(data[:4])
		data = data[4:]

		iplen = ord(data[0])
		data = data[1:]

		if datalen == (26 + 8):  # Using IPv4 addresses
			ip = IP.unpack(data[:4])
			data = data[4:]
			gwip = IP.unpack(data[:4])
			data = data[4:]
		elif datalen == (26 + 32):  # Using IPv6 addresses
			ip = IP.unpack(data[:16])
			data = data[16:]
			gwip = IP.unpack(data[:16])
			data = data[16:]
		else:
			raise Notify(3,5,"Data field length is given as %d, but EVPN route currently support only IPv4 or IPv6(34 or 58)" % iplen)

		label = Labels.unpack(data[:3])

		return cls(rd,esi,etag,label,ip,iplen,gwip,exdata)
Example #4
0
    def rd(self, scope, name, command, tokens, safi):
        try:
            try:
                data = tokens.pop(0)
            except IndexError:
                return self.error.set(self.syntax)

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

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

            nlri = scope[-1]['announce'][-1].nlri
            # overwrite nlri-mpls
            nlri.safi = SAFI(safi)
            nlri.rd = RouteDistinguisher(rd)
            return True
        except ValueError:
            return self.error.set(self.syntax)
Example #5
0
	def unpack (cls, data):
		rd = RouteDistinguisher.unpack(data[:8])
		esi = ESI.unpack(data[8:18])
		etag = EthernetTag.unpack(data[18:22])
		label = Labels.unpack(data[22:25])

		return cls(rd,esi,etag,label,data)
Example #6
0
    def unpack_nlri(cls, afi, safi, bgp, action, addpath):
        length, bgp = ord(bgp[0]), bgp[1:]

        if length & 0xF0 == 0xF0:  # bigger than 240
            extra, bgp = ord(bgp[0]), bgp[1:]
            length = ((length & 0x0F) << 16) + extra

        if length > len(bgp):
            raise Notify(3, 10, 'invalid length at the start of the the flow')

        over = bgp[length:]
        bgp = bgp[:length]

        nlri = Flow(afi, safi, action)

        if safi == SAFI.flow_vpn:
            nlri.rd = RouteDistinguisher(bgp[:8])
            bgp = bgp[8:]

        seen = []

        while bgp:
            what, bgp = ord(bgp[0]), bgp[1:]

            if what not in decode.get(afi, {}):
                raise Notify(
                    3, 10,
                    'unknown flowspec component received for address family %d'
                    % what)

            seen.append(what)
            if sorted(seen) != seen:
                raise Notify(
                    3, 10,
                    'components are not sent in the right order %s' % seen)

            decoded = decode[afi][what]
            klass = factory[afi][what]

            if decoded == 'prefix':
                adding, bgp = klass.make(bgp)
                if not nlri.add(adding):
                    raise Notify(
                        3, 10,
                        'components are incompatible (two sources, two destinations, mix ipv4/ipv6) %s'
                        % seen)
                # logger.parser(LazyFormat("added flow %s (%s) payload " % (klass.NAME,adding),bgp[:-len(left)]))
            else:
                end = False
                while not end:
                    byte, bgp = ord(bgp[0]), bgp[1:]
                    end = CommonOperator.eol(byte)
                    operator = CommonOperator.operator(byte)
                    length = CommonOperator.length(byte)
                    value, bgp = bgp[:length], bgp[length:]
                    adding = klass.decoder(value)
                    nlri.add(klass(operator, adding))
                    # logger.parser(LazyFormat("added flow %s (%s) operator %d len %d payload " % (klass.NAME,adding,byte,length),value))

        return nlri, bgp + over
Example #7
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)
Example #8
0
def rd (tokeniser):
	try:
		value = tokeniser()

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

		# XXX: FIXME: we need much more checks here instead that the blank try/except...

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

	return RouteDistinguisher(distinguisher)
Example #9
0
    def unpack(cls, data):
        rd = RouteDistinguisher.unpack(data[:8])
        esi = ESI.unpack(data[8:18])
        etag = EthernetTag.unpack(data[18:22])
        label = Labels.unpack(data[22:25])

        return cls(rd, esi, etag, label, data)
Example #10
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 = 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', bytes([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 family %s (AFI %d) %s (SAFI %d)' %
                (AFI(afi), int(afi), SAFI(safi), int(safi)))

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

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

        return nlri, bgp
Example #11
0
	def unpack (cls, data):
		rd = RouteDistinguisher.unpack(data[:8])
		etag = EthernetTag.unpack(data[8:12])
		iplen = ord_(data[12])
		if iplen not in (4*8,16*8):
			raise Exception("IP len is %d, but EVPN route currently support only IPv4" % iplen)
		ip = IP.unpack(data[13:13+iplen//8])
		return cls(rd,etag,ip,data)
Example #12
0
    def unpack(cls, data):
        datalen = len(data)
        rd = RouteDistinguisher.unpack(data[:8])
        esi = ESI.unpack(data[8:18])
        etag = EthernetTag.unpack(data[18:22])
        maclength = data[22]

        if maclength > 48 or maclength < 0:
            raise Notify(3, 5, 'invalid MAC Address length in %s' % cls.NAME)
        end = 23 + 6  # MAC length MUST be 6

        mac = MACQUAL.unpack(data[23:end])

        length = data[end]
        iplen = length / 8

        if datalen in [33, 36]:  # No IP information (1 or 2 labels)
            iplenUnpack = 0
            if iplen != 0:
                raise Notify(
                    3, 5,
                    "IP length is given as %d, but current MAC route has no IP information"
                    % iplen)
        elif datalen in [37, 40]:  # Using IPv4 addresses (1 or 2 labels)
            iplenUnpack = 4
            if iplen > 32 or iplen < 0:
                raise Notify(
                    3,
                    5,
                    "IP field length is given as %d, but current MAC route is IPv4 and valus is out of range"
                    % iplen,
                )
        elif datalen in [49, 52]:  # Using IPv6 addresses (1 or 2 labels)
            iplenUnpack = 16
            if iplen > 128 or iplen < 0:
                raise Notify(
                    3,
                    5,
                    "IP field length is given as %d, but current MAC route is IPv6 and valus is out of range"
                    % iplen,
                )
        else:
            raise Notify(
                3, 5,
                "Data field length is given as %d, but does not match one of the expected lengths"
                % datalen)

        payload = data[end + 1:end + 1 + iplenUnpack]
        if payload:
            ip = IP.unpack(data[end + 1:end + 1 + iplenUnpack])
        else:
            ip = None
        label = Labels.unpack(data[end + 1 + iplenUnpack:end + 1 +
                                   iplenUnpack + 3])

        return cls(rd, esi, etag, mac, maclength, label, ip, data)
Example #13
0
File: inet.py Project: doddt/exabgp
    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 = ord(bgp[0])
        bgp = bgp[1:]

        if cls.has_label():
            labels = []
            while bgp and mask >= 8:
                label = int(unpack('!L', chr(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 cls.has_rd():
            mask -= 8 * 8  # the 8 bytes of the route distinguisher
            rd = bgp[:8]
            bgp = bgp[8:]
            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 sand SAFI %d' %
                (afi, safi))

        network, bgp = bgp[:size], bgp[size:]
        padding = '\0' * (IP.length(afi) - size)

        nlri.cidr = CIDR(network + padding, mask)

        return nlri, bgp
Example #14
0
	def generate_rd (rd):
		"""only ip:num is supported atm.code from configure.file"""
		separator = rd.find(':')
		prefix = rd[:separator]
		suffix = int(rd[separator+1:])
		data = [chr(0),chr(1)]
		data.extend([chr(int(_)) for _ in prefix.split('.')])
		data.extend([chr(suffix >> 8),chr(suffix & 0xFF)])
		bin_rd = ''.join(data)
		return RouteDistinguisher(bin_rd)
Example #15
0
	def unpack (cls, data):
		rd = RouteDistinguisher.unpack(data[:8])
		esi = ESI.unpack(data[8:18])
		iplen = ordinal(data[18])

		if iplen not in (32,128):
			raise Notify(3,5,"IP length field is given as %d in current Segment, expecting 32 (IPv4) or 128 (IPv6) bits" % iplen)

		ip = IP.unpack(data[19:19+(iplen//8)])

		return cls(rd,esi,ip,data)
Example #16
0
	def unpack_nlri (cls, afi, safi, bgp, action, addpath):
		# label is 20bits, stored using 3 bytes, 24 bits
		length, = unpack('!H',bgp[0:2])
		if len(bgp) != length+2:
			raise Notify(3,10,'l2vpn vpls message length is not consistent with encoded bgp')
		rd = RouteDistinguisher(bgp[2:10])
		endpoint,offset,size = unpack('!HHH',bgp[10:16])
		base = unpack('!L','\x00'+bgp[16:19])[0] >> 4
		nlri = cls(rd,endpoint,base,offset,size)
		nlri.action = action
		# nlri.nexthop = IP.unpack(nexthop)
		return nlri, bgp[19:]
Example #17
0
    def unpack(cls, afi, safi, bgp, addpath, nexthop, action):
        labels, rd, path_identifier, mask, size, prefix, left = NLRI._nlri(
            afi, safi, bgp, action, addpath)

        nlri = cls(afi, safi, prefix, mask, nexthop, action)
        if labels:
            nlri.labels = Labels(labels)
        if rd:
            nlri.rd = RouteDistinguisher(rd)
        if path_identifier:
            nlri.path_info = PathInfo(None, None, path_identifier)

        return len(bgp) - len(left), nlri
Example #18
0
    def unpack(cls, data):
        rd = RouteDistinguisher.unpack(data[:8])
        esi = ESI.unpack(data[8:18])
        iplen = ord_(data[18])

        if iplen not in (32, 128):
            raise Notify(
                3, 5,
                "IP field length is given as %d in current Segment, expecting 32 (IPv4) or 128 (IPv6) bits"
                % iplen)

        ip = IP.unpack(data[19:19 + (iplen / 8)])

        return cls(rd, esi, ip, data)
Example #19
0
 def unpack(cls, afi, safi, data, addpath, nexthop, action):
     # label is 20bits, stored using 3 bytes, 24 bits
     length, = unpack('!H', data[0:2])
     if len(data) != length + 2:
         raise Notify(
             3, 10,
             'l2vpn vpls message length is not consistent with encoded data'
         )
     rd = RouteDistinguisher(data[2:10])
     ve, offset, size = unpack('!HHH', data[10:16])
     base = unpack('!L', '\x00' + data[16:19])[0] >> 4
     nlri = cls(rd, ve, base, offset, size)
     nlri.action = action
     nlri.nexthop = IP.unpack(nexthop)
     return len(data), nlri
Example #20
0
    def unpack_nlri(cls, afi, safi, bgp, action, addpath):
        code, length = unpack('!HH', bgp[:4])
        if code in cls.registered_bgpls:
            if safi == SAFI.bgp_ls_vpn:
                # Extract Route Distinguisher
                rd = RouteDistinguisher.unpack(bgp[4:12])
                klass = cls.registered_bgpls[code].unpack_nlri(bgp[12 : length + 4], rd)
            else:
                rd = None
                klass = cls.registered_bgpls[code].unpack_nlri(bgp[4 : length + 4], rd)
        else:
            klass = GenericBGPLS(code, bgp[4 : length + 4])
        klass.CODE = code
        klass.action = action
        klass.addpath = addpath

        return klass, bgp[length + 4 :]
Example #21
0
	def unpack_nlri(cls, afi, safi, bgp, action, addpath):
		code, length = unpack('!HH',bgp[:4])
		if code in cls.registered_bgpls:
			if safi == SAFI.bgp_ls_vpn:
				# Extract Route Distinguisher
				rd = RouteDistinguisher.unpack(bgp[4:12])
				klass = cls.registered_bgpls[code].unpack_nlri(bgp[12:length+4],rd)
			else:
				rd = None
				klass = cls.registered_bgpls[code].unpack_nlri(bgp[4:length+4],rd)
		else:
			klass = GenericBGPLS(code,bgp[4:length+4])
		klass.CODE = code
		klass.action = action
		klass.addpath = addpath

		return klass,bgp[length+4:]
Example #22
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 = [bytes([0, 1])]
        data.extend([bytes([int(_)]) for _ in prefix.split('.')])
        data.extend([bytes([suffix >> 8]), bytes([suffix & 0xFF])])
        rtd = b''.join(data)
    else:
        number = int(prefix)
        if number < pow(2, 16) and suffix < pow(2, 32):
            rtd = bytes([0, 0]) + pack('!H', number) + pack('!L', suffix)
        elif number < pow(2, 32) and suffix < pow(2, 16):
            rtd = bytes([0, 2]) + pack('!L', number) + pack('!H', suffix)
        else:
            raise ValueError('invalid route-distinguisher %s' % data)

    return RouteDistinguisher(rtd)