Example #1
0
def next_hop (tokeniser):
	value = tokeniser()
	if value.lower() == 'self':
		# next-hop self is unsupported yet
		raise ValueError('unsupported yet on new format')
	else:
		return NextHop(value)
Example #2
0
 def new(cls, afi, safi, packed, mask, labels, rd, nexthop, action):
     instance = cls(afi, safi, OUT.ANNOUNCE)
     instance.cidr = CIDR(packed, mask)
     instance.labels = labels
     instance.rd = rd
     instance.nexthop = NextHop(IP.ntop(nexthop), nexthop)
     instance.action = action
     return instance
Example #3
0
def next_hop(tokeniser):
    value = tokeniser()

    if value.lower() == 'self':
        return IPSelf(tokeniser.afi), NextHopSelf(tokeniser.afi)
    else:
        ip = IP.create(value)
        return ip, NextHop(ip.top())
Example #4
0
def next_hop(tokeniser):
    value = tokeniser()

    if value.lower() == 'self':
        return NextHopSelf(AFI.ipv4)
    else:
        ip = IP.create(value)
        return NextHop(ip.top(), ip.pack())
Example #5
0
    def callback():
        try:
            descriptions, command = self.parser.extract_neighbors(line)
            peers = reactor.match_neighbors(descriptions)
            if not peers:
                self.log_failure(
                    'no neighbor matching the command : %s' % command,
                    'warning')
                reactor.answer(service, 'error')
                yield True
                return

            changes = self.parser.api_route(command)
            if not changes:
                self.log_failure(
                    'command could not parse route in : %s' % command,
                    'warning')
                reactor.answer(service, 'error')
                yield True
                return

            for change in changes:
                # Change the action to withdraw before checking the route
                change.nlri.action = OUT.WITHDRAW
                # NextHop is a mandatory field (but we do not require in)
                if change.nlri.nexthop is NoNextHop:
                    change.nlri.nexthop = NextHop('0.0.0.0')

                if not ParseStaticRoute.check(change):
                    self.log_message(
                        'invalid route for %s : %s' %
                        (', '.join(peers) if peers else 'all peers',
                         change.extensive()))
                    continue
                if reactor.configuration.inject_change(peers, change):
                    self.log_message(
                        'route removed from %s : %s' %
                        (', '.join(peers) if peers else 'all peers',
                         change.extensive()))
                    yield False
                else:
                    self.log_failure(
                        'route not found on %s : %s' %
                        (', '.join(peers) if peers else 'all peers',
                         change.extensive()))
                    yield False

            reactor.route_update = True
            reactor.answer(service, 'done')
        except ValueError:
            self.log_failure('issue parsing the route')
            reactor.answer(service, 'error')
            yield True
        except IndexError:
            self.log_failure('issue parsing the route')
            reactor.answer(service, 'error')
            yield True
Example #6
0
def next_hop(tokeniser):
    value = tokeniser()

    if value.lower() == 'self':
        return IPSelf(AFI.undefined), NextHopSelf(AFI.undefined)
    else:
        ip = IP.create(value)
        if ip.afi == AFI.ipv4:
            return ip, NextHop(ip.top())
        return ip, None
Example #7
0
    def unpack(cls, data, negotiated):
        nlris = []

        # -- Reading AFI/SAFI
        afi, safi = unpack('!HB', data[:3])
        offset = 3

        # we do not want to accept unknown families
        if negotiated and (afi, safi) not in negotiated.families:
            raise Notify(
                3, 0, 'presented a non-negotiated family %d/%d' % (afi, safi))

        # -- Reading length of next-hop
        len_nh = ord(data[offset])
        offset += 1

        rd = 0

        # check next-hop size
        if afi == AFI.ipv4:
            if safi in (SAFI.unicast, SAFI.multicast):
                if len_nh != 4:
                    raise Notify(
                        3, 0,
                        'invalid ipv4 unicast/multicast next-hop length %d expected 4'
                        % len_nh)
            elif safi in (SAFI.mpls_vpn, ):
                if len_nh != 12:
                    raise Notify(
                        3, 0,
                        'invalid ipv4 mpls_vpn next-hop length %d expected 12'
                        % len_nh)
                rd = 8
            elif safi in (SAFI.flow_ip, ):
                if len_nh not in (0, 4):
                    raise Notify(
                        3, 0,
                        'invalid ipv4 flow_ip next-hop length %d expected 4' %
                        len_nh)
            elif safi in (SAFI.flow_vpn, ):
                if len_nh not in (0, 4):
                    raise Notify(
                        3, 0,
                        'invalid ipv4 flow_vpn next-hop length %d expected 4' %
                        len_nh)
            elif safi in (SAFI.rtc, ):
                if len_nh not in (4, 16):
                    raise Notify(
                        3, 0,
                        'invalid ipv4 rtc next-hop length %d expected 4' %
                        len_nh)
        elif afi == AFI.ipv6:
            if safi in (SAFI.unicast, ):
                if len_nh not in (16, 32):
                    raise Notify(
                        3, 0,
                        'invalid ipv6 unicast next-hop length %d expected 16 or 32'
                        % len_nh)
            elif safi in (SAFI.mpls_vpn, ):
                if len_nh not in (24, 40):
                    raise Notify(
                        3, 0,
                        'invalid ipv6 mpls_vpn next-hop length %d expected 24 or 40'
                        % len_nh)
                rd = 8
            elif safi in (SAFI.flow_ip, ):
                if len_nh not in (0, 16, 32):
                    raise Notify(
                        3, 0,
                        'invalid ipv6 flow_ip next-hop length %d expected 0, 16 or 32'
                        % len_nh)
            elif safi in (SAFI.flow_vpn, ):
                if len_nh not in (0, 16, 32):
                    raise Notify(
                        3, 0,
                        'invalid ipv6 flow_vpn next-hop length %d expected 0, 16 or 32'
                        % len_nh)
        elif afi == AFI.l2vpn:
            if len_nh != 4:
                Notify(3, 0,
                       'invalid l2vpn next-hop length %d expected 4' % len_nh)
        elif afi == AFI.bgpls:
            if len_nh != 4:
                Notify(3, 0,
                       'invalid bgpls next-hop length %d expected 4' % len_nh)
        size = len_nh - rd

        # XXX: FIXME: GET IT FROM CACHE HERE ?
        nhs = data[offset + rd:offset + rd + size]
        nexthops = [nhs[pos:pos + 16] for pos in range(0, len(nhs), 16)]

        # chech the RD is well zero
        if rd and sum([int(ord(_)) for _ in data[offset:8]]) != 0:
            raise Notify(
                3, 0,
                "MP_REACH_NLRI next-hop's route-distinguisher must be zero")

        offset += len_nh

        # Skip a reserved bit as somone had to bug us !
        reserved = ord(data[offset])
        offset += 1

        if reserved != 0:
            raise Notify(3, 0, 'the reserved bit of MP_REACH_NLRI is not zero')

        # Is the peer going to send us some Path Information with the route (AddPath)
        addpath = negotiated.addpath.receive(afi, safi)

        # Reading the NLRIs
        data = data[offset:]

        if not data:
            raise Notify(
                3, 0,
                'No data to decode in an MPREACHNLRI but it is not an EOR %d/%d'
                % (afi, safi))

        while data:
            if nexthops:
                for nexthop in nexthops:
                    nlri, left = NLRI.unpack_nlri(afi, safi, data,
                                                  IN.ANNOUNCED, addpath)
                    nlri.nexthop = NextHop.unpack(nexthop)
                    nlris.append(nlri)
            else:
                nlri, left = NLRI.unpack_nlri(afi, safi, data, IN.ANNOUNCED,
                                              addpath)
                nlris.append(nlri)

            if left == data:
                raise RuntimeError("sub-calls should consume data")

            # logger.parser(LazyFormat("parsed announce mp nlri %s payload " % nlri,data[:length]))
            data = left
        return cls(afi, safi, nlris)
Example #8
0
    def unpack(cls, data, negotiated):
        nlris = []

        # -- Reading AFI/SAFI
        _afi, _safi = unpack('!HB', data[:3])
        afi, safi = AFI.create(_afi), SAFI.create(_safi)
        offset = 3

        # we do not want to accept unknown families
        if negotiated and (afi, safi) not in negotiated.families:
            raise Notify(
                3, 0, 'presented a non-negotiated family %s/%s' % (afi, safi))

        # -- Reading length of next-hop
        len_nh = ordinal(data[offset])
        offset += 1

        if (afi, safi) not in Family.size:
            raise Notify(3, 0, 'unsupported %s %s' % (afi, safi))

        length, rd = Family.size[(afi, safi)]

        if len_nh not in length:
            raise Notify(
                3, 0, 'invalid %s %s next-hop length %d expected %s' %
                (afi, safi, len_nh, ' or '.join(str(_) for _ in length)))

        size = len_nh - rd

        # XXX: FIXME: GET IT FROM CACHE HERE ?
        nhs = data[offset + rd:offset + rd + size]
        nexthops = [nhs[pos:pos + 16] for pos in range(0, len(nhs), 16)]

        # chech the RD is well zero
        if rd and sum([int(ordinal(_)) for _ in data[offset:8]]) != 0:
            raise Notify(
                3, 0,
                "MP_REACH_NLRI next-hop's route-distinguisher must be zero")

        offset += len_nh

        # Skip a reserved bit as somone had to bug us !
        reserved = ordinal(data[offset])
        offset += 1

        if reserved != 0:
            raise Notify(3, 0, 'the reserved bit of MP_REACH_NLRI is not zero')

        # Is the peer going to send us some Path Information with the route (AddPath)
        addpath = negotiated.addpath.receive(afi, safi)

        # Reading the NLRIs
        data = data[offset:]

        if not data:
            raise Notify(
                3, 0,
                'No data to decode in an MPREACHNLRI but it is not an EOR %d/%d'
                % (afi, safi))

        while data:
            if nexthops:
                for nexthop in nexthops:
                    nlri, left = NLRI.unpack_nlri(afi, safi, data,
                                                  IN.ANNOUNCED, addpath)
                    # allow unpack_nlri to return none for "treat as withdraw" controlled by NLRI.unpack_nlri
                    if nlri:
                        nlri.nexthop = NextHop.unpack(nexthop)
                        nlris.append(nlri)
            else:
                nlri, left = NLRI.unpack_nlri(afi, safi, data, IN.ANNOUNCED,
                                              addpath)
                # allow unpack_nlri to return none for "treat as withdraw" controlled by NLRI.unpack_nlri
                if nlri:
                    nlris.append(nlri)

            if left == data:
                raise RuntimeError("sub-calls should consume data")

            data = left
        return cls(afi, safi, nlris)
Example #9
0
	def unpack (cls, data, negotiated):
		nlris = []

		# -- Reading AFI/SAFI
		afi,safi = unpack('!HB',data[:3])
		offset = 3

		# we do not want to accept unknown families
		if negotiated and (afi,safi) not in negotiated.families:
			raise Notify(3,0,'presented a non-negotiated family %d/%d' % (afi,safi))

		# -- Reading length of next-hop
		len_nh = ord_(data[offset])
		offset += 1

		rd = 0

		# check next-hop size
		if afi == AFI.ipv4:
			if safi in (SAFI.unicast,SAFI.multicast):
				if len_nh != 4:
					raise Notify(3,0,'invalid ipv4 unicast/multicast next-hop length %d expected 4' % len_nh)
			elif safi in (SAFI.mpls_vpn,):
				if len_nh != 12:
					raise Notify(3,0,'invalid ipv4 mpls_vpn next-hop length %d expected 12' % len_nh)
				rd = 8
			elif safi in (SAFI.flow_ip,):
				if len_nh not in (0,4):
					raise Notify(3,0,'invalid ipv4 flow_ip next-hop length %d expected 4' % len_nh)
			elif safi in (SAFI.flow_vpn,):
				if len_nh not in (0,4):
					raise Notify(3,0,'invalid ipv4 flow_vpn next-hop length %d expected 4' % len_nh)
			elif safi in (SAFI.rtc,):
				if len_nh not in (4,16):
					raise Notify(3,0,'invalid ipv4 rtc next-hop length %d expected 4' % len_nh)
		elif afi == AFI.ipv6:
			if safi in (SAFI.unicast,):
				if len_nh not in (16,32):
					raise Notify(3,0,'invalid ipv6 unicast next-hop length %d expected 16 or 32' % len_nh)
			elif safi in (SAFI.mpls_vpn,):
				if len_nh not in (24,40):
					raise Notify(3,0,'invalid ipv6 mpls_vpn next-hop length %d expected 24 or 40' % len_nh)
				rd = 8
			elif safi in (SAFI.flow_ip,):
				if len_nh not in (0,16,32):
					raise Notify(3,0,'invalid ipv6 flow_ip next-hop length %d expected 0, 16 or 32' % len_nh)
			elif safi in (SAFI.flow_vpn,):
				if len_nh not in (0,16,32):
					raise Notify(3,0,'invalid ipv6 flow_vpn next-hop length %d expected 0, 16 or 32' % len_nh)
		elif afi == AFI.l2vpn:
			if len_nh != 4:
				Notify(3,0,'invalid l2vpn next-hop length %d expected 4' % len_nh)
		elif afi == AFI.bgpls:
			if len_nh != 4:
				Notify(3,0,'invalid bgpls next-hop length %d expected 4' % len_nh)
		size = len_nh - rd

		# XXX: FIXME: GET IT FROM CACHE HERE ?
		nhs = data[offset+rd:offset+rd+size]
		nexthops = [nhs[pos:pos+16] for pos in range(0,len(nhs),16)]

		# chech the RD is well zero
		if rd and sum([int(ord_(_)) for _ in data[offset:8]]) != 0:
			raise Notify(3,0,"MP_REACH_NLRI next-hop's route-distinguisher must be zero")

		offset += len_nh

		# Skip a reserved bit as somone had to bug us !
		reserved = ord_(data[offset])
		offset += 1

		if reserved != 0:
			raise Notify(3,0,'the reserved bit of MP_REACH_NLRI is not zero')

		# Is the peer going to send us some Path Information with the route (AddPath)
		addpath = negotiated.addpath.receive(afi,safi)

		# Reading the NLRIs
		data = data[offset:]

		if not data:
			raise Notify(3,0,'No data to decode in an MPREACHNLRI but it is not an EOR %d/%d' % (afi,safi))

		while data:
			if nexthops:
				for nexthop in nexthops:
					nlri,left = NLRI.unpack_nlri(afi,safi,data,IN.ANNOUNCED,addpath)
					nlri.nexthop = NextHop.unpack(nexthop)
					nlris.append(nlri)
			else:
				nlri,left = NLRI.unpack_nlri(afi,safi,data,IN.ANNOUNCED,addpath)
				nlris.append(nlri)

			if left == data:
				raise RuntimeError("sub-calls should consume data")

			# logger.parser(LazyFormat("parsed announce mp nlri %s payload " % nlri,data[:length]))
			data = left
		return cls(afi,safi,nlris)
Example #10
0
	def unpack (cls, data, negotiated):
		nlris = []

		# -- Reading AFI/SAFI
		_afi,_safi = unpack('!HB',data[:3])
		afi,safi = AFI.create(_afi),SAFI.create(_safi)
		offset = 3

		# we do not want to accept unknown families
		if negotiated and (afi,safi) not in negotiated.families:
			raise Notify(3,0,'presented a non-negotiated family %s/%s' % (afi,safi))

		# -- Reading length of next-hop
		len_nh = ordinal(data[offset])
		offset += 1

		if (afi,safi) not in Family.size:
			raise Notify(3,0,'unsupported %s %s' % (afi,safi))

		length,rd = Family.size[(afi,safi)]

		if len_nh not in length:
			raise Notify(3,0,'invalid %s %s next-hop length %d expected %s' % (afi,safi,len_nh,' or '.join(str(_) for _ in length)))

		size = len_nh - rd

		# XXX: FIXME: GET IT FROM CACHE HERE ?
		nhs = data[offset+rd:offset+rd+size]
		nexthops = [nhs[pos:pos+16] for pos in range(0,len(nhs),16)]

		# chech the RD is well zero
		if rd and sum([int(ordinal(_)) for _ in data[offset:8]]) != 0:
			raise Notify(3,0,"MP_REACH_NLRI next-hop's route-distinguisher must be zero")

		offset += len_nh

		# Skip a reserved bit as somone had to bug us !
		reserved = ordinal(data[offset])
		offset += 1

		if reserved != 0:
			raise Notify(3,0,'the reserved bit of MP_REACH_NLRI is not zero')

		# Is the peer going to send us some Path Information with the route (AddPath)
		addpath = negotiated.addpath.receive(afi,safi)

		# Reading the NLRIs
		data = data[offset:]

		if not data:
			raise Notify(3,0,'No data to decode in an MPREACHNLRI but it is not an EOR %d/%d' % (afi,safi))

		while data:
			if nexthops:
				for nexthop in nexthops:
					nlri,left = NLRI.unpack_nlri(afi,safi,data,IN.ANNOUNCED,addpath)
					nlri.nexthop = NextHop.unpack(nexthop)
					nlris.append(nlri)
			else:
				nlri,left = NLRI.unpack_nlri(afi,safi,data,IN.ANNOUNCED,addpath)
				nlris.append(nlri)

			if left == data:
				raise RuntimeError("sub-calls should consume data")

			data = left
		return cls(afi,safi,nlris)