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
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()
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:], )
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
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, }, })
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, }
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:]))
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]))
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))
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:]
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
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)
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 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
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)
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
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)
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
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)
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))
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:]))
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 = []
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)
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()
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)
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)
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)
def aggregator(tokeniser): value = tokeniser() if value != '(': tokeniser.rewind(value) return None try: as_number, address = tokeniser().split(':') except (ValueError, IndexError): raise ValueError('invalid aggregator') value = tokeniser() if value != ')': raise ValueError('invalid aggregator') local_as = ASN(as_number) local_address = RouterID(address) # XXX: This is buggy it can be an Aggregator4 return Aggregator(local_as, local_address)
def unpack(data): asn, rate = unpack('!Hf', data[2:8]) return TrafficRate(ASN(asn), rate, data[:8])