Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds support for Unique Local Addresses #2856

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions scapy/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
IPV6_ADDR_GLOBAL = 0x00
IPV6_ADDR_LINKLOCAL = 0x20
IPV6_ADDR_SITELOCAL = 0x40 # deprecated since Sept. 2004 by RFC 3879
IPV6_ADDR_UNIQUE_LOCAL = 0x08
IPV6_ADDR_SCOPE_MASK = 0xF0
# IPV6_ADDR_COMPATv4 = 0x80 # deprecated; i.e. ::/96
# IPV6_ADDR_MAPPED = 0x1000 # i.e.; ::ffff:0.0.0.0/96
Expand Down
36 changes: 17 additions & 19 deletions scapy/utils6.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
from scapy.config import conf
from scapy.base_classes import Gen
from scapy.data import IPV6_ADDR_GLOBAL, IPV6_ADDR_LINKLOCAL, \
IPV6_ADDR_SITELOCAL, IPV6_ADDR_LOOPBACK, IPV6_ADDR_UNICAST,\
IPV6_ADDR_MULTICAST, IPV6_ADDR_6TO4, IPV6_ADDR_UNSPECIFIED
IPV6_ADDR_SITELOCAL, IPV6_ADDR_UNIQUE_LOCAL, IPV6_ADDR_LOOPBACK, \
IPV6_ADDR_UNICAST, IPV6_ADDR_MULTICAST, IPV6_ADDR_6TO4, \
IPV6_ADDR_UNSPECIFIED
from scapy.utils import strxor
from scapy.compat import orb, chb
from scapy.pton_ntop import inet_pton, inet_ntop
Expand Down Expand Up @@ -59,12 +60,14 @@ def cset_sort(x, y):
return -res

cset = []
if in6_isgladdr(addr) or in6_isuladdr(addr):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not convinced that this change is correct. Did you test it on Linux with unique local addresses? It seems that the Linux kernel does not specify IPV6_ADDR_UNIQUE_LOCAL. Therefore, this patch will likely break address selection.

if in6_isgladdr(addr):
cset = (x for x in laddr if x[1] == IPV6_ADDR_GLOBAL)
elif in6_islladdr(addr):
cset = (x for x in laddr if x[1] == IPV6_ADDR_LINKLOCAL)
elif in6_issladdr(addr):
cset = (x for x in laddr if x[1] == IPV6_ADDR_SITELOCAL)
elif in6_isuladdr(addr):
cset = (x for x in laddr if x[1] == IPV6_ADDR_UNIQUE_LOCAL)
elif in6_ismaddr(addr):
if in6_ismnladdr(addr):
cset = [('::1', 16, conf.loopback_name)]
Expand Down Expand Up @@ -164,29 +167,27 @@ def rfc3484_cmp(source_a, source_b):
return candidate_set[0]


# Think before modify it : for instance, FE::1 does exist and is unicast
# there are many others like that.
# TODO : integrate Unique Local Addresses
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not remove the other comments.

def in6_getAddrType(addr):
naddr = inet_pton(socket.AF_INET6, addr)
paddr = inet_ntop(socket.AF_INET6, naddr) # normalize
addrType = 0
# _Assignable_ Global Unicast Address space
# is defined in RFC 3513 as those in 2000::/3
if ((orb(naddr[0]) & 0xE0) == 0x20):
if in6_isgladdr(addr):
addrType = (IPV6_ADDR_UNICAST | IPV6_ADDR_GLOBAL)
if naddr[:2] == b' \x02': # Mark 6to4 @
if in6_isaddr6to4(addr): # Mark 6to4
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please replace @ with address instead of removing it.

addrType |= IPV6_ADDR_6TO4
elif orb(naddr[0]) == 0xff: # multicast
addrScope = paddr[3]
if addrScope == '2':
elif in6_ismaddr(addr): # multicast
if in6_ismlladdr(addr):
addrType = (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_MULTICAST)
elif addrScope == 'e':
elif in6_ismgladdr(addr):
addrType = (IPV6_ADDR_GLOBAL | IPV6_ADDR_MULTICAST)
else:
addrType = (IPV6_ADDR_GLOBAL | IPV6_ADDR_MULTICAST)
elif ((orb(naddr[0]) == 0xfe) and ((int(paddr[2], 16) & 0xC) == 0x8)):
elif in6_islladdr(addr):
addrType = (IPV6_ADDR_UNICAST | IPV6_ADDR_LINKLOCAL)
elif in6_isuladdr(addr):
addrType = (IPV6_ADDR_UNICAST | IPV6_ADDR_UNIQUE_LOCAL)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should also be IPV6_ADDR_GLOBAL

elif paddr == "::1":
addrType = IPV6_ADDR_LOOPBACK
elif paddr == "::":
Expand Down Expand Up @@ -704,11 +705,6 @@ def in6_isuladdr(str):
"""
return in6_isincluded(str, 'fc00::', 7)

# TODO : we should see the status of Unique Local addresses against
# global address space.
# Up-to-date information is available through RFC 3587.
# We should review function behavior based on its content.


def in6_isgladdr(str):
"""
Expand Down Expand Up @@ -783,12 +779,14 @@ def in6_getscope(addr):
"""
Returns the scope of the address.
"""
if in6_isgladdr(addr) or in6_isuladdr(addr):
if in6_isgladdr(addr):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to https://tools.ietf.org/html/rfc4193#section-3.3 the scope is global. This function should not be modified.

scope = IPV6_ADDR_GLOBAL
elif in6_islladdr(addr):
scope = IPV6_ADDR_LINKLOCAL
elif in6_issladdr(addr):
scope = IPV6_ADDR_SITELOCAL
elif in6_isuladdr(addr):
scope = IPV6_ADDR_UNIQUE_LOCAL
elif in6_ismaddr(addr):
if in6_ismgladdr(addr):
scope = IPV6_ADDR_GLOBAL
Expand Down
4 changes: 4 additions & 0 deletions test/regression.uts
Original file line number Diff line number Diff line change
Expand Up @@ -2923,6 +2923,9 @@ in6_getAddrType("FF02::1") == (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_MULTICAST)
= in6_getAddrType - Unicast Link-Local address
in6_getAddrType("FE80::") == (IPV6_ADDR_UNICAST | IPV6_ADDR_LINKLOCAL)

= in6_getAddrType - Unicast Unique local address
in6_getAddrType("FC00::") == (IPV6_ADDR_UNICAST | IPV6_ADDR_UNIQUE_LOCAL)

= in6_getAddrType - Loopback address
in6_getAddrType("::1") == IPV6_ADDR_LOOPBACK

Expand Down Expand Up @@ -10136,6 +10139,7 @@ assert in6_getscope("fe80::2807") == IPV6_ADDR_LINKLOCAL
assert in6_getscope("ff02::2807") == IPV6_ADDR_LINKLOCAL
assert in6_getscope("ff0e::2807") == IPV6_ADDR_GLOBAL
assert in6_getscope("ff05::2807") == IPV6_ADDR_SITELOCAL
assert in6_getscope("fc00::2807") == IPV6_ADDR_UNIQUE_LOCAL
assert in6_getscope("ff01::2807") == IPV6_ADDR_LOOPBACK
assert in6_getscope("::1") == IPV6_ADDR_LOOPBACK

Expand Down