diff --git a/capirca/lib/cisco.py b/capirca/lib/cisco.py index 5c1cd8eb..cd15d8eb 100644 --- a/capirca/lib/cisco.py +++ b/capirca/lib/cisco.py @@ -698,7 +698,10 @@ def GetProtocolName(proto, af: int): proto_name = IOSXEMap._PROTO_NAMES[af][proto] return proto_name except KeyError: - return proto + try: + return IOSXEMap._PROTO_NAMES[af][int(proto)] + except (KeyError, ValueError): + return proto @staticmethod def GetPortName(port, proto: str): @@ -766,8 +769,10 @@ def __init__(self, term, af=4, proto_int=True, enable_dsmo=False, self.text_af = 'inet' else: self.text_af = 'inet6' + self.ALLOWED_PROTO_STRINGS = list(self.ALLOWED_PROTO_STRINGS) self.ALLOWED_PROTO_STRINGS.extend([self.PROTO_MAP.get(x) # pyrefly: ignore[bad-argument-type] - for x in self.ALWAYS_PROTO_NUM]) + for x in self.ALWAYS_PROTO_NUM + if self.PROTO_MAP.get(x) not in self.ALLOWED_PROTO_STRINGS]) def __str__(self): # Verify platform specific terms. Skip whole term if platform does not @@ -822,7 +827,7 @@ def __str__(self): protocol = ['hbh'] elif self.proto_int: protocol = [proto if proto in self.ALLOWED_PROTO_STRINGS - else self.PROTO_MAP.get(proto) + else self.PROTO_MAP.get(proto, proto) for proto in self.term.protocol] else: protocol = self.term.protocol @@ -1225,7 +1230,7 @@ def __str__(self): else: protocol = [proto if proto in self.ALLOWED_PROTO_STRINGS - else self.PROTO_MAP.get(proto) + else self.PROTO_MAP.get(proto, proto) for proto in self.term.protocol] # addresses diff --git a/tests/lib/cisco_test.py b/tests/lib/cisco_test.py index cdb7ffe6..bbf31927 100644 --- a/tests/lib/cisco_test.py +++ b/tests/lib/cisco_test.py @@ -469,6 +469,12 @@ action:: accept } """ +GOOD_TERM_31_NUMERIC_PROTO = """ +term good_term_31_numeric_proto { + protocol:: 50 + action:: accept +} +""" SUPPORTED_TOKENS = { 'action', @@ -1893,5 +1899,53 @@ def testIcmpTypeCodeNames(self): ) + def testNumericProtocol(self): + pol = policy.ParsePolicy( + GOOD_HEADER + GOOD_TERM_31_NUMERIC_PROTO, self.naming + ) + acl = cisco.Cisco(pol, EXP_INFO) + self.assertIn('permit 50 any any', str(acl)) + self.assertNotIn('None', str(acl)) + + def testNumericProtocolObjectGroup(self): + pol = policy.ParsePolicy( + GOOD_OBJGRP_HEADER_1 + GOOD_TERM_31_NUMERIC_PROTO, self.naming + ) + acl = cisco.Cisco(pol, EXP_INFO) + self.assertIn('permit 50 any any', str(acl)) + self.assertNotIn('None', str(acl)) + + def testNumericProtocolInet6(self): + header = """ +header { + target:: cisco test-filter inet6 +} +""" + pol = policy.ParsePolicy(header + GOOD_TERM_31_NUMERIC_PROTO, self.naming) + acl = cisco.Cisco(pol, EXP_INFO) + self.assertIn('permit 50 any any', str(acl)) + self.assertNotIn('None', str(acl)) + + def testNumericProtocolConfigureReplaceCompatible(self): + header = """ +header { + target:: cisco test-filter extended configure_replace_compatible +} +""" + pol = policy.ParsePolicy(header + GOOD_TERM_31_NUMERIC_PROTO, self.naming) + acl = cisco.Cisco(pol, EXP_INFO) + self.assertIn('permit esp any any', str(acl)) + self.assertNotIn('None', str(acl)) + + def testAllowedProtoStringsNotMutated(self): + before = list(cisco.Term.ALLOWED_PROTO_STRINGS) + pol = policy.ParsePolicy( + GOOD_HEADER + GOOD_TERM_31_NUMERIC_PROTO, self.naming + ) + _ = cisco.Cisco(pol, EXP_INFO) + _ = cisco.Cisco(pol, EXP_INFO) + self.assertEqual(before, cisco.Term.ALLOWED_PROTO_STRINGS) + + if __name__ == '__main__': absltest.main()