Exemple #1
0
    def unpack_nlri(cls, afi, safi, bgp, action, addpath):

        length = bgp[0]

        if length == 0:
            return cls(afi, safi, action, ASN(0), None), bgp[1:]

        if length < 8 * 4:
            raise Exception("incorrect RT length: %d (should be >=32,<=96)" %
                            length)

        # We are reseting the flags on the RouteTarget extended
        # community, because they do not make sense for an RTC route

        return (
            cls(
                afi,
                safi,
                action,
                ASN(unpack('!L', bgp[1:5])[0]),
                RouteTarget.unpack(
                    bytes([RTC.resetFlags(bgp[5])]) + bgp[6:13]),
            ),
            bgp[13:],
        )
Exemple #2
0
 def __init__(self):
     self.update({
         'description': 'a test neighbor',
         'router-id': RouterID('127.0.0.1'),
         'local-address': IPv4('127.0.0.1'),
         'peer-address': IPv4('127.0.0.1'),
         'host-name': 'localhost',
         'domain-name': 'localdomain',
         'peer-as': ASN('65500'),
         'local-as': ASN('65500'),
         'hold-time': HoldTime(180),
         'capability': {
             'asn4': False,
             'add-path': 0,
             'extended_message': False,
             'nexthop': None,
             'route-refresh': False,
             'graceful-restart': False,
             'multi-session': None,
             'add-path': None,
             'aigp': None,
             'operational': None,
             'extended-message': True,
         },
     })
Exemple #3
0
class FakeNeighbor(object):
    description = 'a test neighbor'
    router_id = RouterID('127.0.0.1')
    local_address = IPv4('127.0.0.1')
    peer_address = IPv4('127.0.0.1')
    host_name = 'localhost'
    domain_name = 'localdomain'
    peer_as = ASN('65500')
    local_as = ASN('65500')
    hold_time = HoldTime(180)
    asn4 = False
    add_path = 0
    extended_message = False
    nexthop = None

    # capability
    route_refresh = False
    graceful_restart = False
    multisession = None
    add_path = None
    aigp = None
    operational = None

    @staticmethod
    def families():
        return NLRI.known_families()
Exemple #4
0
    def setUp(self):
        self.negotiated = {}

        for asn4 in (True, False):
            neighbor = FakeNeighbor()
            neighbor.asn4 = asn4

            capa = Capabilities().new(neighbor, False)
            capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families()

            # path = {}
            # for f in NLRI.known_families():
            # 	if neighbor.add_path:
            # 		path[f] = neighbor.add_path
            # capa[Capability.CODE.ADD_PATH] = path

            routerid_1 = str(neighbor.router_id)
            routerid_2 = '.'.join(
                str((int(_) + 1) % 250)
                for _ in str(neighbor.router_id).split('.', -1))

            o1 = Open(Version(4), ASN(neighbor.local_as), HoldTime(180),
                      RouterID(routerid_1), capa)
            o2 = Open(Version(4), ASN(neighbor.peer_as), HoldTime(180),
                      RouterID(routerid_2), capa)

            negotiated = Negotiated(neighbor)
            negotiated.sent(o1)
            negotiated.received(o2)

            self.negotiated[asn4] = negotiated
Exemple #5
0
    def setUp(self):
        self.negotiated = {}

        for asn4 in (True, False):
            neighbor = FakeNeighbor()
            neighbor.asn4 = asn4

            capa = Capabilities().new(neighbor, False)
            capa[Capability.CODE.MULTIPROTOCOL] = neighbor.families()

            # path = {}
            # for f in NLRI.known_families():
            # 	if neighbor.add_path:
            # 		path[f] = neighbor.add_path
            # capa[Capability.CODE.ADD_PATH] = path

            o1 = Open(Version(4), ASN(neighbor.local_as), HoldTime(180),
                      RouterID(neighbor.local_address.top()), capa)
            o2 = Open(Version(4), ASN(neighbor.peer_as), HoldTime(180),
                      RouterID(neighbor.peer_address.top()), capa)

            negotiated = Negotiated(neighbor)
            negotiated.sent(o1)
            negotiated.received(o2)

            self.negotiated[asn4] = negotiated
Exemple #6
0
	def __init__ (self,aggregator):
		asn = 0
		for value in (ord(_) for _ in aggregator[:-4]):
			asn = (asn << 8) + value
		self.asn=ASN(asn)
		self.speaker=Inet(AFI.ipv4,SAFI.unicast,aggregator[-4:])
		self._str = '%s:%s' % (self.asn,self.speaker)
Exemple #7
0
class Aggregator (Attribute):
	ID = AttributeID.AGGREGATOR
	FLAG = Flag.TRANSITIVE|Flag.OPTIONAL
	MULTIPLE = False

	def __init__ (self,aggregator):
		asn = 0
		for value in (ord(_) for _ in aggregator[:-4]):
			asn = (asn << 8) + value
		self.asn=ASN(asn)
		self.speaker=Inet(AFI.ipv4,SAFI.unicast,aggregator[-4:])
		self._str = '%s:%s' % (self.asn,self.speaker)

	def pack (self,asn4,as4agg=False):
		if as4agg:
			backup = self.ID
			self.ID = AttributeID.AS4_AGGREGATOR
			packed = self._attribute(self.asn.pack(True)+self.speaker.pack())
			self.ID = backup
			return packed
		elif asn4:
			return self._attribute(self.asn.pack(True)+self.speaker.pack())
		elif not self.asn.asn4():
			return self._attribute(self.asn.pack(False)+self.speaker.pack())
		else:
			return self._attribute(self.asn.trans()+self.speaker.pack()) + self.pack(True,True)


	def __len__ (self):
		raise RuntimeError('size can be 6 or 8 - we can not say')

	def __str__ (self):
		return self._str
Exemple #8
0
 def __init__(self, local, remote, asn, peer):
     self['local-address'] = IPv4(local)
     self['peer_address'] = IPv4(remote)
     self['peer-as'] = ASN(asn)
     self['local-as'] = ASN(peer)
     self['capability'] = {
         'asn4': True,
     }
Exemple #9
0
    def unpack(afi, safi, data):
        length = ord(data[0])

        if length == 0:
            return RouteTargetConstraint(afi, safi, ASN(0), None)

        return RouteTargetConstraint(afi, safi,
                                     ASN(unpack('!L', data[1:5])[0]),
                                     RouteTarget.unpack(data[5:]))
Exemple #10
0
    def unpack(cls, afi, safi, data, addpath, nexthop, action):
        length = ord(data[0])

        if length == 0:
            return 1, RouteTargetConstraint(afi, safi, action, ASN(0), None)

        # safeguard: let's ignore any ext com flag that might be set here
        packedRT = RouteTargetConstraint.resetFlags(data[5]) + data[6:13]

        return 13, RouteTargetConstraint(afi, safi, action, nexthop,
                                         ASN(unpack('!L', data[1:5])[0]),
                                         RouteTarget.unpack(packedRT))
Exemple #11
0
    def unpack(cls, afi, safi, data, addpath, nexthop, action):
        length = ord(data[0])

        if length == 0:
            return 1, cls(afi, safi, action, NoNextHop, ASN(0), None)

        # We are reseting the flags on the RouteTarget extended
        # community, because they do not make sense for an RTC route

        return 13, cls(
            afi, safi, action, nexthop, ASN(unpack('!L', data[1:5])[0]),
            RouteTarget.unpack(RTC.resetFlags(data[5]) + data[6:13]))
Exemple #12
0
    def unpack_nlri(cls, afi, safi, bgp, action, addpath):

        length = ord(bgp[0])

        if length == 0:
            return 1, cls(afi, safi, action, ASN(0), None)

        # We are reseting the flags on the RouteTarget extended
        # community, because they do not make sense for an RTC route

        return cls(afi, safi, action, ASN(unpack('!L', bgp[1:5])[0]),
                   RouteTarget.unpack(RTC.resetFlags(bgp[5]) +
                                      bgp[6:13])), bgp[13:]
Exemple #13
0
    def __init__(self):
        self.sent_open = None
        self.received_open = None

        self.holdtime = HoldTime(0)
        self.local_as = ASN(0)
        self.peer_as = ASN(0)
        self.families = []
        self.asn4 = False
        self.addpath = RequirePath()
        self.multisession = False
        self.msg_size = 4096 - 19
        self.operational = False
Exemple #14
0
 def newASN(value):
     if value.count('.'):
         high, low = value.split('.', 1)
         as_number = (int(high) << 16) + int(low)
     else:
         as_number = int(value)
     return ASN(as_number)
Exemple #15
0
    def aggregator(self, scope, name, command, tokens):
        try:
            if tokens:
                if tokens.pop(0) != '(':
                    raise ValueError('invalid aggregator syntax')
                asn, address = tokens.pop(0).split(':')
                if tokens.pop(0) != ')':
                    raise ValueError('invalid aggregator syntax')
                local_as = ASN(asn)
                local_address = RouterID(address)
            else:
                local_as = scope[-1]['local-as']
                local_address = scope[-1]['local-address']
        except (ValueError, IndexError):
            return self.error.set(self.syntax)
        except KeyError:
            return self.error(
                'local-as and/or local-address missing from neighbor/group to make aggregator'
            )
        except ValueError:
            return self.error.set(self.syntax)

        scope[-1]['announce'][-1].attributes.add(
            Aggregator(local_as, local_address))
        return True
Exemple #16
0
class Open (Message):
	ID = Message.CODE.OPEN
	TYPE = chr(Message.CODE.OPEN)

	def __init__ (self, version, asn, router_id, capabilities, hold_time):
		self.version = Version(version)
		self.asn = ASN(asn)
		self.hold_time = HoldTime(hold_time)
		self.router_id = RouterID(router_id)
		self.capabilities = capabilities

	def message (self):
		return self._message("%s%s%s%s%s" % (
			self.version.pack(),
			self.asn.trans(),
			self.hold_time.pack(),
			self.router_id.pack(),
			self.capabilities.pack()
		))

	def __str__ (self):
		return "OPEN version=%d asn=%d hold_time=%s router_id=%s capabilities=[%s]" % (self.version, self.asn, self.hold_time, self.router_id,self.capabilities)

	@classmethod
	def unpack_message (cls, data, _):
		version = ord(data[0])
		if version != 4:
			# Only version 4 is supported nowdays..
			raise Notify(2,1,data[0])
		asn = unpack('!H',data[1:3])[0]
		hold_time = unpack('!H',data[3:5])[0]
		numeric = unpack('!L',data[5:9])[0]
		router_id = "%d.%d.%d.%d" % (numeric >> 24,(numeric >> 16) & 0xFF,(numeric >> 8) & 0xFF,numeric & 0xFF)
		capabilities = Capabilities.unpack(data[9:])
		return cls(version,asn,router_id,capabilities,hold_time)
Exemple #17
0
def aspath(tokeniser):
    as_seq = []
    as_set = []
    value = tokeniser()
    inset = False
    try:
        if value == '[':
            while True:
                value = tokeniser()
                if value == ',':
                    continue
                if value in ('(', '['):
                    inset = True
                    while True:
                        value = tokeniser()
                        if value == ')':
                            break
                        as_set.append(asn(tokeniser, value))
                if value == ')':
                    inset = False
                    continue
                if value == ']':
                    if inset:
                        inset = False
                        continue
                    break
                as_seq.append(ASN(tokeniser, value))
        else:
            as_seq.append(asn(tokeniser, value))
    except ValueError:
        raise ValueError('could not parse as-path')
    return ASPath(as_seq, as_set)
Exemple #18
0
class Open(Message):
    ID = Message.CODE.OPEN
    TYPE = chr(Message.CODE.OPEN)

    def __init__(self, version, asn, router_id, capabilities, hold_time):
        self.version = Version(version)
        self.asn = ASN(asn)
        self.hold_time = HoldTime(hold_time)
        self.router_id = RouterID(router_id)
        self.capabilities = capabilities

    def message(self, negotiated=None):
        return self._message(
            "%s%s%s%s%s" %
            (self.version.pack(), self.asn.trans(), self.hold_time.pack(),
             self.router_id.pack(), self.capabilities.pack()))

    def __str__(self):
        return "OPEN version=%d asn=%d hold_time=%s router_id=%s capabilities=[%s]" % (
            self.version, self.asn, self.hold_time, self.router_id,
            self.capabilities)

    @classmethod
    def unpack_message(cls, data, _=None):
        version = ord(data[0])
        if version != 4:
            # Only version 4 is supported nowdays..
            raise Notify(2, 1, data[0])
        asn = unpack('!H', data[1:3])[0]
        hold_time = unpack('!H', data[3:5])[0]
        numeric = unpack('!L', data[5:9])[0]
        router_id = "%d.%d.%d.%d" % (numeric >> 24, (numeric >> 16) & 0xFF,
                                     (numeric >> 8) & 0xFF, numeric & 0xFF)
        capabilities = Capabilities.unpack(data[9:])
        return cls(version, asn, router_id, capabilities, hold_time)
Exemple #19
0
 def discard(self, scope, name, command, tokens):
     # README: We are setting the ASN as zero as that what Juniper (and Arbor) did when we created a local flow route
     try:
         scope[-1]['announce'][-1].attributes[
             Attribute.CODE.EXTENDED_COMMUNITY].add(TrafficRate(ASN(0), 0))
         return True
     except ValueError:
         return self.error.set(self.syntax)
Exemple #20
0
    def __init__(self, neighbor):
        self.neighbor = neighbor

        self.sent_open = None
        self.received_open = None

        self.holdtime = HoldTime(0)
        self.local_as = ASN(0)
        self.peer_as = ASN(0)
        self.families = []
        self.asn4 = False
        self.addpath = RequirePath()
        self.multisession = False
        self.msg_size = self.MAX_SIZE
        self.operational = False
        self.refresh = REFRESH.ABSENT  # pylint: disable=E1101
        self.aigp = None
Exemple #21
0
    def __init__(self, neighbor):
        self.neighbor = neighbor

        self.sent_open = None
        self.received_open = None

        self.holdtime = HoldTime(0)
        self.local_as = ASN(0)
        self.peer_as = ASN(0)
        self.families = []
        self.asn4 = False
        self.addpath = RequirePath()
        self.multisession = False
        self.msg_size = 4096
        self.operational = False
        self.refresh = REFRESH.absent
        self.aigp = None
Exemple #22
0
    def _new_aspaths(cls, data, asn4, klass=None):
        as_set = []
        as_seq = []
        as_cset = []
        as_cseq = []

        backup = data

        unpacker = {
            False: '!H',
            True: '!L',
        }
        size = {
            False: 2,
            True: 4,
        }
        as_choice = {
            ASPath.AS_SEQUENCE: as_seq,
            ASPath.AS_SET: as_set,
            ASPath.AS_CONFED_SEQUENCE: as_cseq,
            ASPath.AS_CONFED_SET: as_cset,
        }

        upr = unpacker[asn4]
        length = size[asn4]

        try:

            while data:
                stype = data[0]
                slen = data[1]

                if stype not in (ASPath.AS_SET, ASPath.AS_SEQUENCE,
                                 ASPath.AS_CONFED_SEQUENCE,
                                 ASPath.AS_CONFED_SET):
                    raise Notify(3, 11, 'invalid AS Path type sent %d' % stype)

                end = 2 + (slen * length)
                sdata = data[2:end]
                data = data[end:]
                # Eat the data and ignore it if the ASPath attribute is know known
                asns = as_choice.get(stype, [])

                for _ in range(slen):
                    asn = unpack(upr, sdata[:length])[0]
                    asns.append(ASN(asn))
                    sdata = sdata[length:]

        except IndexError:
            raise Notify(3, 11,
                         'not enough data to decode AS_PATH or AS4_PATH')
        except error:  # struct
            raise Notify(3, 11,
                         'not enough data to decode AS_PATH or AS4_PATH')

        if klass:
            return klass(as_seq, as_set, as_cseq, as_cset, backup)
        return cls(as_seq, as_set, as_cseq, as_cset, backup)
Exemple #23
0
def rate_limit(tokeniser):
    # README: We are setting the ASN as zero as that what Juniper (and Arbor) did when we created a local flow route
    speed = int(tokeniser())
    if speed < 9600 and speed != 0:
        log.warning("rate-limiting flow under 9600 bytes per seconds may not work", 'configuration')
    if speed > 1000000000000:
        speed = 1000000000000
        log.warning("rate-limiting changed for 1 000 000 000 000 bytes from %s" % speed, 'configuration')
    return ExtendedCommunities().add(TrafficRate(ASN(0), speed))
Exemple #24
0
    def __init__(self, neighbor):
        self.neighbor = neighbor

        self.sent_open = None
        self.received_open = None

        self.holdtime = HoldTime(0)
        self.local_as = ASN(0)
        self.peer_as = ASN(0)
        self.families = []
        self.nexthop = []
        self.asn4 = False
        self.addpath = RequirePath()
        self.multisession = False
        self.msg_size = ExtendedMessage.INITIAL_SIZE
        self.operational = False
        self.refresh = REFRESH.ABSENT  # pylint: disable=E1101
        self.aigp = neighbor['capability']['aigp']
        self.mismatch = []
Exemple #25
0
 def unpack_message(cls, data, _=None):
     version = data[0]
     if version != 4:
         # Only version 4 is supported nowdays..
         raise Notify(2, 1, bytes(data[0], 'ascii'))
     asn = unpack('!H', data[1:3])[0]
     hold_time = unpack('!H', data[3:5])[0]
     numeric = unpack('!L', data[5:9])[0]
     router_id = "%d.%d.%d.%d" % (numeric >> 24, (numeric >> 16) & 0xFF, (numeric >> 8) & 0xFF, numeric & 0xFF)
     return cls(Version(version), ASN(asn), HoldTime(hold_time), RouterID(router_id), Capabilities.unpack(data[9:]))
Exemple #26
0
def asn(tokeniser, value=None):
    value = tokeniser() if value is None else value
    try:
        if value.count('.'):
            high, low = value.split('.', 1)
            as_number = (int(high) << 16) + int(low)
        else:
            as_number = int(value)
        return ASN(as_number)
    except ValueError:
        raise ValueError('"%s" is an invalid ASN' % value)
Exemple #27
0
class Neighbor:
    description = 'a test neighbor'
    router_id = RouterID('127.0.0.1')
    local_address = IPv4('127.0.0.1')
    peer_address = IPv4('127.0.0.1')
    peer_as = ASN('65500')
    local_as = ASN('65500')
    hold_time = HoldTime(180)
    asn4 = False
    add_path = 0

    # capability
    route_refresh = False
    graceful_restart = False
    multisession = None
    add_path = None
    aigp = None

    @staticmethod
    def families():
        return known_families()
Exemple #28
0
    def __new_aspaths(cls, data, asn4, klass=None):
        as_set = []
        as_seq = []
        backup = data

        unpacker = {
            False: '!H',
            True: '!L',
        }
        size = {
            False: 2,
            True: 4,
        }
        as_choice = {
            ASPath.AS_SEQUENCE: as_seq,
            ASPath.AS_SET: as_set,
        }

        upr = unpacker[asn4]
        length = size[asn4]

        try:

            while data:
                stype = ord(data[0])
                slen = ord(data[1])

                if stype not in (ASPath.AS_SET, ASPath.AS_SEQUENCE):
                    raise Notify(3, 11, 'invalid AS Path type sent %d' % stype)

                end = 2 + (slen * length)
                sdata = data[2:end]
                data = data[end:]
                asns = as_choice[stype]

                for i in range(slen):
                    asn = unpack(upr, sdata[:length])[0]
                    asns.append(ASN(asn))
                    sdata = sdata[length:]

        except IndexError:
            raise Notify(3, 11,
                         'not enough data to decode AS_PATH or AS4_PATH')
        except error:  # struct
            raise Notify(3, 11,
                         'not enough data to decode AS_PATH or AS4_PATH')

        if klass:
            return klass(as_seq, as_set, backup)
        return cls(as_seq, as_set, backup)
def asn(tokeniser, value=None):
    if value is None:
        if not tokeniser.tokens:
            raise ValueError('an asn is required')

    value = tokeniser()
    try:
        if value.count('.'):
            high, low = value.split('.', 1)
            as_number = (int(high) << 16) + int(low)
        else:
            as_number = int(value)
        return ASN(as_number)
    except ValueError:
        raise ValueError('"%s" is an invalid ASN' % value)
Exemple #30
0
    def _new_aspaths(cls, data, asn4, klass=None):
        backup = data

        unpacker = {
            False: '!H',
            True: '!L',
        }
        size = {
            False: 2,
            True: 4,
        }

        upr = unpacker[asn4]
        length = size[asn4]

        aspath = []

        try:
            while data:
                stype = data[0]
                slen = data[1]

                if stype not in cls._DISPATCH:
                    raise Notify(3, 11, 'invalid AS Path type sent %d' % stype)

                end = 2 + (slen * length)
                sdata = data[2:end]
                data = data[end:]
                # Eat the data and ignore it if the ASPath attribute is know known
                asns = cls._DISPATCH[stype]()

                for _ in range(slen):
                    asn = unpack(upr, sdata[:length])[0]
                    asns.append(ASN(asn))
                    sdata = sdata[length:]

                aspath.append(asns)

        except IndexError:
            raise Notify(3, 11, 'not enough data to decode AS_PATH or AS4_PATH')
        except error:  # struct
            raise Notify(3, 11, 'not enough data to decode AS_PATH or AS4_PATH')

        if klass:
            return klass(aspath, backup)
        return cls(aspath, backup)
Exemple #31
0
 def rate_limit(self, scope, name, command, tokens):
     # README: We are setting the ASN as zero as that what Juniper (and Arbor) did when we created a local flow route
     try:
         speed = int(tokens[0])
         if speed < 9600 and speed != 0:
             self.logger.configuration(
                 "rate-limiting flow under 9600 bytes per seconds may not work",
                 'warning')
         if speed > 1000000000000:
             speed = 1000000000000
             self.logger.configuration(
                 "rate-limiting changed for 1 000 000 000 000 bytes from %s"
                 % tokens[0], 'warning')
         scope[-1]['announce'][-1].attributes[
             Attribute.CODE.EXTENDED_COMMUNITY].add(
                 TrafficRate(ASN(0), speed))
         return True
     except ValueError:
         return self.error.set(self.syntax)
Exemple #32
0
class Open (Message):
	TYPE = chr(Message.Type.OPEN)

	def __init__ (self,version,asn,router_id,capabilities,hold_time):
		self.version = Version(version)
		self.asn = ASN(asn)
		self.hold_time = HoldTime(hold_time)
		self.router_id = RouterID(router_id)
		self.capabilities = capabilities

	def message (self):
		return self._message("%s%s%s%s%s" % (
			self.version.pack(),
			self.asn.trans(),
			self.hold_time.pack(),
			self.router_id.pack(),
			self.capabilities.pack()
		))

	def __str__ (self):
		return "OPEN version=%d asn=%d hold_time=%s router_id=%s capabilities=[%s]" % (self.version, self.asn, self.hold_time, self.router_id,self.capabilities)
Exemple #33
0
	def __init__ (self, version, asn, router_id, capabilities, hold_time):
		self.version = Version(version)
		self.asn = ASN(asn)
		self.hold_time = HoldTime(hold_time)
		self.router_id = RouterID(router_id)
		self.capabilities = capabilities
Exemple #34
0
	def __init__ (self,value=0):
		ASN.__init__(self,value)
	def unpack (cls,data,negotiated):
		if negotiated.asn4:
			return cls(ASN.unpack(data[:4]),IPv4.unpack(data[-4:]))
		return cls(ASN.unpack(data[:2]),IPv4.unpack(data[-4:]))
Exemple #36
0
	def unpack (what,instance,data):
		# XXX: FIXME: if instance is not ASN(0) we have two ASN - raise
		instance = ASN.unpack(data,ASN4)
		return instance
Exemple #37
0
	def unpack_capability (instance, data, capability=None):  # pylint: disable=W0613
		# XXX: FIXME: if instance is not ASN(0) we have two ASN - raise
		instance = ASN.unpack(data,ASN4)
		return instance