def unpack_message(cls, data, negotiated): # pylint: disable=W0613 what = Type(unpack('!H', data[0:2])[0]) length = unpack('!H', data[2:4])[0] decode, klass = cls.registered_operational.get(what, ('unknown', None)) if decode == 'advisory': afi = unpack('!H', data[4:6])[0] safi = ordinal(data[6]) data = data[7:length + 4] return klass(afi, safi, data) elif decode == 'query': afi = unpack('!H', data[4:6])[0] safi = ordinal(data[6]) routerid = RouterID.unpack(data[7:11]) sequence = unpack('!L', data[11:15])[0] return klass(afi, safi, routerid, sequence) elif decode == 'counter': afi = unpack('!H', data[4:6])[0] safi = ordinal(data[6]) routerid = RouterID.unpack(data[7:11]) sequence = unpack('!L', data[11:15])[0] counter = unpack('!L', data[15:19])[0] return klass(afi, safi, routerid, sequence, counter) else: print('ignoring ATM this kind of message')
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
def unpack_message (cls, data, negotiated): # pylint: disable=W0613 what = Type(unpack('!H',data[0:2])[0]) length = unpack('!H',data[2:4])[0] decode,klass = cls.registered_operational.get(what,('unknown',None)) if decode == 'advisory': afi = unpack('!H',data[4:6])[0] safi = ordinal(data[6]) data = data[7:length+4] return klass(afi,safi,data) elif decode == 'query': afi = unpack('!H',data[4:6])[0] safi = ordinal(data[6]) routerid = RouterID.unpack(data[7:11]) sequence = unpack('!L',data[11:15])[0] return klass(afi,safi,routerid,sequence) elif decode == 'counter': afi = unpack('!H',data[4:6])[0] safi = ordinal(data[6]) routerid = RouterID.unpack(data[7:11]) sequence = unpack('!L',data[11:15])[0] counter = unpack('!L',data[15:19])[0] return klass(afi,safi,routerid,sequence,counter) else: print('ignoring ATM this kind of message')
def OperationalFactory (data): what = Type(unpack('!H',data[0:2])[0]) length = unpack('!H',data[2:4])[0] if what == OperationalType.ADM: afi = unpack('!H',data[4:6])[0] safi = ord(data[6]) data = data[7:length+4] return Advisory.ADM(afi,safi,data) elif what == OperationalType.ASM: afi = unpack('!H',data[4:6])[0] safi = ord(data[6]) data = data[7:length+4] return Advisory.ASM(afi,safi,data) elif what == OperationalType.RPCQ: afi = unpack('!H',data[4:6])[0] safi = ord(data[6]) routerid = RouterID(unpack('!H',data[7:9])[0]) sequence = unpack('!H',data[9:11])[0] return State.RPCQ(afi,safi,routerid,sequence) elif what == OperationalType.RPCP: afi = unpack('!H',data[4:6])[0] safi = ord(data[6]) routerid = RouterID(unpack('!H',data[7:9])[0]) sequence = unpack('!H',data[9:11])[0] count = unpack('!H',data[11:15])[0] return State.RPCQ(afi,safi,routerid,sequence,count) else: print 'ignoring ATM this kind of message'
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 OperationalFactory(data): what = Type(unpack('!H', data[0:2])[0]) length = unpack('!H', data[2:4])[0] decode, klass = OperationalGroup.get(what, ('unknown', None)) if decode == 'advisory': afi = unpack('!H', data[4:6])[0] safi = ord(data[6]) data = data[7:length + 4] return klass(afi, safi, data) elif decode == 'query': afi = unpack('!H', data[4:6])[0] safi = ord(data[6]) routerid = RouterID('.'.join(str(ord(_)) for _ in data[7:11])) sequence = unpack('!L', data[11:15])[0] return klass(afi, safi, routerid, sequence) elif decode == 'counter': afi = unpack('!H', data[4:6])[0] safi = ord(data[6]) routerid = RouterID('.'.join(str(ord(_)) for _ in data[7:11])) sequence = unpack('!L', data[11:15])[0] counter = unpack('!L', data[15:19])[0] return klass(afi, safi, routerid, sequence, counter) elif decode == 'interface': afi = unpack('!H', data[4:6])[0] safi = ord(data[6]) routerid = RouterID('.'.join(str(ord(_)) for _ in data[7:11])) sequence = unpack('!L', data[11:15])[0] rxc = unpack('!L', data[15:19])[0] txc = unpack('!L', data[19:23])[0] return klass(afi, safi, routerid, sequence, rxc, txc) else: print 'ignoring ATM this kind of message'
def __init__ (self,what,afi,safi,routerid,sequence=None,data=''): self.routerid = routerid self.routerid = RouterID(routerid) self.sequence = self._sequence() if sequence is None else sequence OperationalFamily.__init__( self,what, afi,safi, '%s%s%s' % (self.routerid.pack(),pack('!H',self.sequence),data) )
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)
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)
def validate (self, neighbor): if self.peer_as != neighbor.peer_as: return (2,2,'ASN in OPEN (%d) did not match ASN expected (%d)' % (self.received_open.asn,neighbor.peer_as)) # RFC 6286 : https://tools.ietf.org/html/rfc6286 # XXX: FIXME: check that router id is not self if self.received_open.router_id == RouterID('0.0.0.0'): return (2,3,'0.0.0.0 is an invalid router_id') if self.received_open.asn == neighbor.local_as: # router-id must be unique within an ASN if self.received_open.router_id == neighbor.router_id: return (2,3,'BGP Identifier collision, same router-id (%s) on both sides of this IBGP session' % self.received_open.router_id) if self.received_open.hold_time and self.received_open.hold_time < 3: return (2,6,'Hold Time is invalid (%d)' % self.received_open.hold_time) if self.multisession not in (True,False): # XXX: FIXME: should we not use a string and perform a split like we do elswhere ? # XXX: FIXME: or should we use this trick in the other case ? return self.multisession s = set(self.sent_open.capabilities.get(Capability.CODE.MULTIPROTOCOL,[])) r = set(self.received_open.capabilities.get(Capability.CODE.MULTIPROTOCOL,[])) mismatch = s ^ r for family in mismatch: self.mismatch.append(('exabgp' if family in r else 'peer',family)) return None
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 validate (self,neighbor): if not self.asn4: if neighbor.local_as.asn4(): return (2,0,'peer does not speak ASN4, we are stuck') else: # we will use RFC 4893 to convey new ASN to the peer # XXX: FIXME pass if self.peer_as != neighbor.peer_as: return (2,2,'ASN in OPEN (%d) did not match ASN expected (%d)' % (self.received_open.asn,neighbor.peer_as)) # RFC 6286 : http://tools.ietf.org/html/rfc6286 # XXX: FIXME: check that router id is not self if self.received_open.router_id == RouterID('0.0.0.0'): return (2,3,'0.0.0.0 is an invalid router_id') if self.received_open.asn == neighbor.local_as: # router-id must be unique within an ASN if self.received_open.router_id == neighbor.router_id: return (2,3,'BGP Indendifier collision, same router-id (%s) on both side of this IBGP session' % self.received_open.router_id) if self.received_open.hold_time and self.received_open.hold_time < 3: return (2,6,'Hold Time is invalid (%d)' % self.received_open.hold_time) if self.multisession not in (True,False): # XXX: FIXME: should we not use a string and perform a split like we do elswhere ? # XXX: FIXME: or should we use this trick in the other case ? return self.multisession return None
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, }, })
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 _operational(klass, parameters, tokeniser): def utf8(string): return string.encode('utf-8') def valid(_): return True def u32(_): return int(_) <= 0xFFFFFFFF def u64(_): return int(_) <= 0xFFFFFFFFFFFFFFFF def advisory(_): return len(_.encode('utf-8')) <= MAX_ADVISORY + 2 # the two quotes convert = {'afi': AFI.value, 'safi': SAFI.value, 'sequence': int, 'counter': int, 'advisory': utf8} validate = { 'afi': AFI.value, 'safi': SAFI.value, 'sequence': u32, 'counter': u64, } number = len(parameters) * 2 tokens = [] while len(tokens) != number: tokens.append(tokeniser()) data = {} while tokens and parameters: command = tokens.pop(0).lower() value = tokens.pop(0) if command == 'router-id': if isipv4(value): data['routerid'] = RouterID(value) else: raise ValueError('invalid operational value for %s' % command) continue expected = parameters.pop(0) if command != expected: raise ValueError('invalid operational syntax, unknown argument %s' % command) if not validate.get(command, valid)(value): raise ValueError('invalid operational value for %s' % command) data[command] = convert[command](value) if tokens or parameters: raise ValueError('invalid advisory syntax, missing argument(s) %s' % ', '.join(parameters)) if 'routerid' not in data: data['routerid'] = None return klass(**data)
def test_2_open(self): capabilities = Capabilities() o = Open(4, 65500, '127.0.0.1', capabilities, 180) self.assertEqual(o.version, 4) self.assertEqual(o.asn, 65500) self.assertEqual(o.router_id, RouterID('127.0.0.1')) self.assertEqual(o.hold_time, 180) self.assertEqual(o.capabilities, {})
def router_id(self, scope, name, command, tokens): try: ip = RouterID(tokens[0]) except (IndexError, ValueError): return self.error.set('"%s" is an invalid IP address' % ' '.join(tokens)) scope[-1][command] = ip return True
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:]))
class SequencedOperationalFamily (OperationalFamily): __sequence_number = 0 def _sequence (self): self.__sequence_number +=1 return self.__sequence_number def __init__ (self,what,afi,safi,routerid,sequence=None,data=''): self.routerid = routerid self.routerid = RouterID(routerid) self.sequence = self._sequence() if sequence is None else sequence OperationalFamily.__init__( self,what, afi,safi, '%s%s%s' % (self.routerid.pack(),pack('!H',self.sequence),data) )
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)
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()
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)
message_id = 1 body = ''.join([ chr(c) for c in [ 0x4, 0xff, 0xfe, 0x0, 0xb4, 0x0, 0x0, 0x0, 0x0, 0x20, 0x2, 0x6, 0x1, 0x4, 0x0, 0x1, 0x0, 0x1, 0x2, 0x6, 0x1, 0x4, 0x0, 0x2, 0x0, 0x1, 0x2, 0x2, 0x80, 0x0, 0x2, 0x2, 0x2, 0x0, 0x2, 0x6, 0x41, 0x4, 0x0, 0x0, 0xff, 0xfe ] ]) negotiated = {'invalid': 'test'} o = Message.unpack(message_id, body, negotiated) self.assertEqual(o.version, 4) self.assertEqual(o.asn, 65534) self.assertEqual(o.router_id, RouterID('0.0.0.0')) self.assertEqual(o.hold_time, 180) for k, v in o.capabilities.items(): self.assertEqual(v, check_capa[k]) def test_2_open(self): capabilities = Capabilities() o = Open(4, 65500, '127.0.0.1', capabilities, 180) self.assertEqual(o.version, 4) self.assertEqual(o.asn, 65500) self.assertEqual(o.router_id, RouterID('127.0.0.1')) self.assertEqual(o.hold_time, 180) self.assertEqual(o.capabilities, {}) if __name__ == '__main__':
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 new_connections(self): if not self.serving: return yield None reactor = self._reactor ranged_neighbor = [] for connection in self._connected(): self.logger.debug('new connection received %s' % connection.name(), 'network') for key in reactor.peers: peer = reactor.peers[key] neighbor = peer.neighbor connection_local = IP.create(connection.local).address() neighbor_peer_start = neighbor.peer_address.address() neighbor_peer_next = neighbor_peer_start + neighbor.range_size if not neighbor_peer_start <= connection_local < neighbor_peer_next: continue connection_peer = IP.create(connection.peer).address() neighbor_local = neighbor.local_address.address() if connection_peer != neighbor_local: if not neighbor.auto_discovery: continue # we found a range matching for this connection # but the peer may already have connected, so # we need to iterate all individual peers before # handling "range" peers if neighbor.range_size > 1: ranged_neighbor.append(peer.neighbor) continue denied = peer.handle_connection(connection) if denied: self.logger.debug( 'refused connection from %s due to the state machine' % connection.name(), 'network') break self.logger.debug( 'accepted connection from %s' % connection.name(), 'network') break else: # we did not break (and nothign was found/done or we have group match) matched = len(ranged_neighbor) if matched > 1: self.logger.debug( 'could not accept connection from %s (more than one neighbor match)' % connection.name(), 'network') reactor.asynchronous.schedule( str(uuid.uuid1()), 'sending notification (6,5)', connection.notification( 6, 5, 'could not accept the connection (more than one neighbor match)' )) return if not matched: self.logger.debug( 'no session configured for %s' % connection.name(), 'network') reactor.asynchronous.schedule( str(uuid.uuid1()), 'sending notification (6,3)', connection.notification( 6, 3, 'no session configured for the peer')) return new_neighbor = copy.copy(ranged_neighbor[0]) new_neighbor.range_size = 1 new_neighbor.generated = True new_neighbor.local_address = IP.create(connection.peer) new_neighbor.peer_address = IP.create(connection.local) if not new_neighbor.router_id: new_neighbor.router_id = RouterID.create(connection.local) new_peer = Peer(new_neighbor, reactor) denied = new_peer.handle_connection(connection) if denied: self.logger.debug( 'refused connection from %s due to the state machine' % connection.name(), 'network') return reactor.peers[new_neighbor.name()] = new_peer return
def routerid(tokeniser): return RouterID(tokeniser())
def new_connections (self): if not self.serving: return yield None reactor = self._reactor ranged_neighbor = [] for connection in self._connected(): self.logger.debug('new connection received %s' % connection.name(),'network') for key in reactor.peers: peer = reactor.peers[key] neighbor = peer.neighbor connection_local = IP.create(connection.local).address() neighbor_peer_start = neighbor.peer_address.address() neighbor_peer_next = neighbor_peer_start + neighbor.range_size if not neighbor_peer_start <= connection_local < neighbor_peer_next: continue connection_peer = IP.create(connection.peer).address() neighbor_local = neighbor.local_address.address() if connection_peer != neighbor_local: if not neighbor.auto_discovery: continue # we found a range matching for this connection # but the peer may already have connected, so # we need to iterate all individual peers before # handling "range" peers if neighbor.range_size > 1: ranged_neighbor.append(peer.neighbor) continue denied = peer.handle_connection(connection) if denied: self.logger.debug('refused connection from %s due to the state machine' % connection.name(),'network') break self.logger.debug('accepted connection from %s' % connection.name(),'network') break else: # we did not break (and nothign was found/done or we have group match) matched = len(ranged_neighbor) if matched > 1: self.logger.debug('could not accept connection from %s (more than one neighbor match)' % connection.name(),'network') reactor.asynchronous.schedule(str(uuid.uuid1()), 'sending notification (6,5)', connection.notification( 6, 5, 'could not accept the connection (more than one neighbor match)')) return if not matched: self.logger.debug('no session configured for %s' % connection.name(),'network') reactor.asynchronous.schedule(str(uuid.uuid1()), 'sending notification (6,3)', connection.notification( 6, 3, 'no session configured for the peer')) return new_neighbor = copy.copy(ranged_neighbor[0]) new_neighbor.range_size = 1 new_neighbor.generated = True new_neighbor.local_address = IP.create(connection.peer) new_neighbor.peer_address = IP.create(connection.local) new_neighbor.router_id = RouterID.create(connection.local) new_peer = Peer(new_neighbor,self) denied = new_peer.handle_connection(connection) if denied: self.logger.debug('refused connection from %s due to the state machine' % connection.name(),'network') return reactor.peers[new_neighbor.name()] = new_peer return
def _operational(self, klass, parameters, tokens): def utf8(string): return string.encode('utf-8')[1:-1] convert = { 'afi': AFI.value, 'safi': SAFI.value, 'sequence': int, 'counter': long, 'advisory': utf8 } def valid(_): return True def u32(_): return int(_) <= 0xFFFFFFFF def u64(_): return long(_) <= 0xFFFFFFFFFFFFFFFF def advisory(_): return len(_.encode('utf-8')) <= MAX_ADVISORY + 2 # the two quotes validate = { 'afi': AFI.value, 'safi': SAFI.value, 'sequence': u32, 'counter': u64, } number = len(parameters) * 2 tokens = formated(tokens).split(' ', number - 1) if len(tokens) != number: return self.error.set( 'invalid operational syntax, wrong number of arguments') data = {} while tokens and parameters: command = tokens.pop(0).lower() value = tokens.pop(0) if command == 'router-id': if isipv4(value): data['routerid'] = RouterID(value) else: self.error.set('invalid operational value for %s' % command) return None continue expected = parameters.pop(0) if command != expected: self.error.set( 'invalid operational syntax, unknown argument %s' % command) return None if not validate.get(command, valid)(value): self.error.set('invalid operational value for %s' % command) return None data[command] = convert[command](value) if tokens or parameters: self.error.set('invalid advisory syntax, missing argument(s) %s' % ', '.join(parameters)) return None if 'routerid' not in data: data['routerid'] = None return klass(**data)
def router_id(tokeniser): value = tokeniser() try: return RouterID(value) except ValueError: raise ValueError('"%s" is an invalid router-id' % value)
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