Skip to content

Commit ba1ca2e

Browse files
Add IPv6 :type and :scope (#3498)
Co-authored-by: blackout <[email protected]>
1 parent 4c98bc6 commit ba1ca2e

File tree

4 files changed

+47
-5
lines changed

4 files changed

+47
-5
lines changed

synapse/lib/modelrev.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,7 @@ async def revModel_0_2_22(self, layers):
731731
await self._normFormSubs(layers, 'inet:ipv4', cmprvalu='100.64.0.0/10')
732732

733733
async def revModel_0_2_23(self, layers):
734+
await self._normFormSubs(layers, 'inet:ipv6')
734735
await self._normFormSubsByProp(layers, 'it:sec:cpe', 'v2_2')
735736

736737
async def runStorm(self, text, opts=None):

synapse/models/inet.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,35 @@ def getAddrType(ip):
5454

5555
return 'unicast'
5656

57+
# https://en.wikipedia.org/wiki/IPv6_address#Address_scopes
58+
ipv6_multicast_scopes = {
59+
'ff00:': 'reserved',
60+
'ff01:': 'interface-local',
61+
'ff02:': 'link-local',
62+
'ff03:': 'realm-local',
63+
'ff04:': 'admin-local',
64+
'ff05:': 'site-local',
65+
'ff08:': 'organization-local',
66+
'ff0e:': 'global',
67+
'ff0f:': 'reserved',
68+
}
69+
70+
scopes_enum = 'reserved,interface-local,link-local,realm-local,admin-local,site-local,organization-local,global,unassigned'
71+
72+
def getAddrScope(ipv6):
73+
74+
if ipv6.is_loopback:
75+
return 'link-local'
76+
77+
if ipv6.is_link_local:
78+
return 'link-local'
79+
80+
if ipv6.is_multicast:
81+
pref = ipv6.compressed[:5]
82+
return ipv6_multicast_scopes.get(pref, 'unassigned')
83+
84+
return 'global'
85+
5786
class Addr(s_types.Str):
5887

5988
def postTypeInit(self):
@@ -579,15 +608,18 @@ def _normPyStr(self, valu):
579608
v6 = ipaddress.IPv6Address(valu)
580609
v4 = v6.ipv4_mapped
581610

582-
subs = {'type': getAddrType(v6)}
611+
subs = {
612+
'type': getAddrType(v6),
613+
'scope': getAddrScope(v6),
614+
}
583615

584616
if v4 is not None:
585617
v4_int = self.modl.type('inet:ipv4').norm(v4.compressed)[0]
586618
v4_str = self.modl.type('inet:ipv4').repr(v4_int)
587619
subs['ipv4'] = v4_int
588620
return f'::ffff:{v4_str}', {'subs': subs}
589621

590-
return ipaddress.IPv6Address(valu).compressed, {'subs': subs}
622+
return v6.compressed, {'subs': subs}
591623

592624
except Exception as e:
593625
raise s_exc.BadTypeValu(valu=valu, name=self.name, mesg=str(e)) from None
@@ -2057,6 +2089,13 @@ def getModelDefs(self):
20572089

20582090
('loc', ('loc', {}), {
20592091
'doc': 'The geo-political location string for the IPv6.'}),
2092+
2093+
('type', ('str', {}), {
2094+
'doc': 'The type of IP address (e.g., private, multicast, etc.).'}),
2095+
2096+
('scope', ('str', {'enums': scopes_enum}), {
2097+
'doc': 'The IPv6 scope of the address (e.g., global, link-local, etc.).'}),
2098+
20602099
)),
20612100

20622101
('inet:mac', {}, (

synapse/tests/test_lib_modelrev.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,8 +430,8 @@ async def test_modelrev_0_2_22(self):
430430
self.eq(node.props.get('type'), 'shared')
431431

432432
async def test_modelrev_0_2_23(self):
433-
434433
async with self.getRegrCore('model-0.2.23') as core:
434+
self.len(1, await core.nodes('inet:ipv6="ff01::1" +:type=multicast +:scope=interface-local'))
435435

436436
nodes = await core.nodes('it:sec:cpe:vendor=10web')
437437
self.len(1, nodes)

synapse/tests/test_model_inet.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -986,11 +986,13 @@ async def test_ipv6(self):
986986
# Type Tests ======================================================
987987
t = core.model.type(formname)
988988

989-
info = {'subs': {'type': 'loopback'}}
989+
info = {'subs': {'type': 'loopback', 'scope': 'link-local'}}
990990
self.eq(t.norm('::1'), ('::1', info))
991991
self.eq(t.norm('0:0:0:0:0:0:0:1'), ('::1', info))
992992

993-
info = {'subs': {'type': 'private'}}
993+
self.eq(t.norm('ff01::1'), ('ff01::1', {'subs': {'type': 'multicast', 'scope': 'interface-local'}}))
994+
995+
info = {'subs': {'type': 'private', 'scope': 'global'}}
994996
self.eq(t.norm('2001:0db8:0000:0000:0000:ff00:0042:8329'), ('2001:db8::ff00:42:8329', info))
995997
self.eq(t.norm('2001:0db8:0000:0000:0000:ff00:0042\u200b:8329'), ('2001:db8::ff00:42:8329', info))
996998
self.raises(s_exc.BadTypeValu, t.norm, 'newp')

0 commit comments

Comments
 (0)