Skip to content

Commit

Permalink
Add IPv6Obj() with an IPv4Address embedded in it
Browse files Browse the repository at this point in the history
  • Loading branch information
mpenning committed Nov 15, 2023
1 parent 91cb564 commit e78ec52
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 18 deletions.
29 changes: 15 additions & 14 deletions ciscoconfparse/ccp_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,20 @@
_RGX_CISCO_RANGE = re.compile(_CISCO_RANGE_STR)

####################### Begin IPv6 #############################
_IPV6_REGEX_STR = r"""(?!:::\S+?$) # Negative Lookahead for 3 colons
(?P<addr> # Begin a group named 'addr'
(?P<opt1>{0}(?::{0}){{7}}) # no double colons, option 1
|(?P<opt2>(?:{0}:){{1}}(?::{0}){{1,6}}) # match fe80::1
|(?P<opt3>(?:{0}:){{2}}(?::{0}){{1,5}}) # match fe80:a::1
|(?P<opt4>(?:{0}:){{3}}(?::{0}){{1,4}}) # match fe80:a:b::1
|(?P<opt5>(?:{0}:){{4}}(?::{0}){{1,3}}) # match fe80:a:b:c::1
|(?P<opt6>(?:{0}:){{5}}(?::{0}){{1,2}}) # match fe80:a:b:c:d::1
|(?P<opt7>(?:{0}:){{6}}(?::{0}){{1,1}}) # match fe80:a:b:c:d:e::1
|(?P<opt8>:(?::{0}){{1,7}}) # ipv6 with leading double colons
|(?P<opt9>(?:{0}:){{1,7}}:) # ipv6 with trailing double colons
|(?P<opt10>(?:::)) # ipv6 bare double colons (default route)
)([/\s](?P<masklen>\d+))* # match 'masklen' and end 'addr' group
_IPV6_REGEX_STR = r"""(?!:::\S+?$) # Negative Lookahead for 3 colons
(?P<addr> # Begin a group named 'addr'
(?P<opt1>{0}(?::{0}){{7}}) # no double colons, option 1
|(?P<opt2>[0-9a-fA-F\:]+?\d+\.\d+\.\d+\.\d+) # ipv4 embedded in an ipv6 address
|(?P<opt3>(?:{0}:){{1}}(?::{0}){{1,6}}) # match fe80::1
|(?P<opt4>(?:{0}:){{2}}(?::{0}){{1,5}}) # match fe80:a::1
|(?P<opt5>(?:{0}:){{3}}(?::{0}){{1,4}}) # match fe80:a:b::1
|(?P<opt6>(?:{0}:){{4}}(?::{0}){{1,3}}) # match fe80:a:b:c::1
|(?P<opt7>(?:{0}:){{5}}(?::{0}){{1,2}}) # match fe80:a:b:c:d::1
|(?P<opt8>(?:{0}:){{6}}(?::{0}){{1,1}}) # match fe80:a:b:c:d:e::1
|(?P<opt9>:(?::{0}){{1,7}}) # ipv6 with leading double colons
|(?P<opt10>(?:{0}:){{1,7}}:) # ipv6 with trailing double colons
|(?P<opt11>(?:::)) # ipv6 bare double colons (default route)
)([/\s](?P<masklen>\d+))* # match 'masklen' and end 'addr' group
""".format(_IPV6_RGX_CLS)

_IPV6_REGEX_STR_COMPRESSED1 = r"""(?!:::\S+?$)(?P<addr1>(?P<opt1_1>{0}(?::{0}){{7}})|(?P<opt1_2>(?:{0}:){{1}}(?::{0}){{1,6}})|(?P<opt1_3>(?:{0}:){{2}}(?::{0}){{1,5}})|(?P<opt1_4>(?:{0}:){{3}}(?::{0}){{1,4}})|(?P<opt1_5>(?:{0}:){{4}}(?::{0}){{1,3}})|(?P<opt1_6>(?:{0}:){{5}}(?::{0}){{1,2}})|(?P<opt1_7>(?:{0}:){{6}}(?::{0}){{1,1}})|(?P<opt1_8>:(?::{0}){{1,7}})|(?P<opt1_9>(?:{0}:){{1,7}}:)|(?P<opt1_10>(?:::)))""".format(_IPV6_RGX_CLS)
Expand Down Expand Up @@ -1879,7 +1880,7 @@ def __init__(self, v6addr_prefixlen=None, strict=False, debug=0):
# Example 'v6_groupdict'
# v6_groupdict = {'addr': '2b00:cd80:14:10::1', 'opt1': None, 'opt2': None, 'opt3': None, 'opt4': None, 'opt5': '2b00:cd80:14:10::1', 'opt6': None, 'opt7': None, 'opt8': None, 'opt9': None, 'opt10': None, 'masklen': '64'}
v6_groupdict = v6_str_rgx.groupdict()
for key in ["addr", "opt1", "opt2", "opt3", "opt4", "opt5", "opt6", "opt7", "opt8", "opt9", "opt10",]:
for key in ["addr", "opt1", "opt2", "opt3", "opt4", "opt5", "opt6", "opt7", "opt8", "opt9", "opt10", "opt11"]:
_ipv6 = v6_groupdict[key]
if _ipv6 is not None:
break
Expand Down
3 changes: 1 addition & 2 deletions ciscoconfparse/models_cisco.py
Original file line number Diff line number Diff line change
Expand Up @@ -2283,10 +2283,9 @@ def trunk_vlans_allowed(self):
elif vdict["allowed"] != "_nomatch_":
retval = CiscoRange(vdict["allowed"], result_type=int)

print("----")
# Inspect vdict keys in a specific order to ensure best results...
for key in ["allowed", "add", "except", "remove"]:
_value = vdict[key]
print(f"KEY: {key}, VALUE: {_value}")

if isinstance(_value, str):
_value = _value.strip()
Expand Down
17 changes: 15 additions & 2 deletions tests/test_Ccp_Util.py
Original file line number Diff line number Diff line change
Expand Up @@ -597,12 +597,25 @@ def testIPv6Obj_lt_01():
"""Simple less_than test"""
assert IPv6Obj("::1") < IPv6Obj("::2")

def testIPv6Obj_IPv4_embedded_in_IPv6_01():
"""Test IPv6Obj with an IPv4 address (192.168.1.254) embedded in an IPv6 address"""
assert IPv6Obj("::192.168.1.254") == IPv6Obj("::c0a8:1fe")

def test_collapse_addresses_01():
def testIPv6Obj_IPv4_embedded_in_IPv6_02():
"""Test IPv6Obj with an IPv4 address (192.0.2.33) embedded in an IPv6 address"""
assert IPv6Obj("2001:db8:122:344::192.0.2.33") == IPv6Obj("2001:db8:122:344::c000:221")

net_collapsed = ipaddress.collapse_addresses([IPv4Network('192.0.0.0/22'), IPv4Network('192.0.2.128/25')])
def testIPv6Obj_IPv4_embedded_in_IPv6_03():
"""Test IPv6Obj with an RFC 6052 NAT64 prefix (64:ff9b::) using IPv4 address (10.20.0.1) embedded in an IPv6 address"""
assert IPv6Obj("64:ff9b::192.0.2.33") == IPv6Obj("64:ff9b::c000:221")

def testIPv6Obj_IPv4_embedded_in_IPv6_04():
"""Test IPv6Obj with an IPv4 address (192.0.2.4) embedded in an IPv6 address"""
assert IPv6Obj("::ffff:192.0.2.4") == IPv6Obj("::ffff:c000:204")

def test_collapse_addresses_01():

net_collapsed = ipaddress.collapse_addresses([IPv4Network('192.0.0.0/22'), IPv4Network('192.0.2.128/25')])
for idx, entry in enumerate(net_collapsed):
if idx==0:
assert entry == IPv4Network("192.0.0.0/22")
Expand Down

0 comments on commit e78ec52

Please sign in to comment.