summaryrefslogtreecommitdiffstats
path: root/scripts/external_libs/scapy-python3-0.18/scapy/utils6.py
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2016-03-21 16:03:47 +0200
committerimarom <imarom@cisco.com>2016-03-21 16:03:47 +0200
commitb89efa188810bf95a9d245e69e2961b5721c3b0f (patch)
tree454273ac6c4ae972ebb8a2c86b893296970b4fa9 /scripts/external_libs/scapy-python3-0.18/scapy/utils6.py
parentf72c6df9d2e9998ae1f3529d729ab7930b35785a (diff)
scapy python 2/3
Diffstat (limited to 'scripts/external_libs/scapy-python3-0.18/scapy/utils6.py')
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/utils6.py823
1 files changed, 0 insertions, 823 deletions
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/utils6.py b/scripts/external_libs/scapy-python3-0.18/scapy/utils6.py
deleted file mode 100644
index d9112aa5..00000000
--- a/scripts/external_libs/scapy-python3-0.18/scapy/utils6.py
+++ /dev/null
@@ -1,823 +0,0 @@
-## This file is part of Scapy
-## See http://www.secdev.org/projects/scapy for more informations
-## Copyright (C) Philippe Biondi <phil@secdev.org>
-## This program is published under a GPLv2 license
-
-## Copyright (C) 2005 Guillaume Valadon <guedou@hongo.wide.ad.jp>
-## Arnaud Ebalard <arnaud.ebalard@eads.net>
-
-"""
-Utility functions for IPv6.
-"""
-
-import itertools
-from .config import conf
-from .data import *
-from .utils import *
-
-def cmp_to_key(mycmp):
- 'Convert a cmp= function into a key= function'
- class K(object):
- def __init__(self, obj, *args):
- self.obj = obj
- def __lt__(self, other):
- return mycmp(self.obj, other.obj) < 0
- def __gt__(self, other):
- return mycmp(self.obj, other.obj) > 0
- def __eq__(self, other):
- return mycmp(self.obj, other.obj) == 0
- def __le__(self, other):
- return mycmp(self.obj, other.obj) <= 0
- def __ge__(self, other):
- return mycmp(self.obj, other.obj) >= 0
- def __ne__(self, other):
- return mycmp(self.obj, other.obj) != 0
- return K
-
-
-
-def construct_source_candidate_set(addr, plen, laddr, loname):
- """
- Given all addresses assigned to a specific interface ('laddr' parameter),
- this function returns the "candidate set" associated with 'addr/plen'.
-
- Basically, the function filters all interface addresses to keep only those
- that have the same scope as provided prefix.
-
- This is on this list of addresses that the source selection mechanism
- will then be performed to select the best source address associated
- with some specific destination that uses this prefix.
- """
- def cset_sort(x,y):
- x_global = 0
- if in6_isgladdr(x):
- x_global = 1
- y_global = 0
- if in6_isgladdr(y):
- y_global = 1
- res = y_global - x_global
- if res != 0 or y_global != 1:
- return res
- # two global addresses: if one is native, it wins.
- if not in6_isaddr6to4(x):
- return -1;
- return -res
-
- cset = []
- if in6_isgladdr(addr) or in6_isuladdr(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_ismaddr(addr):
- if in6_ismnladdr(addr):
- cset = [('::1', 16, loname)]
- elif in6_ismgladdr(addr):
- cset = [ x for x in laddr if x[1] == IPV6_ADDR_GLOBAL ]
- elif in6_ismlladdr(addr):
- cset = [ x for x in laddr if x[1] == IPV6_ADDR_LINKLOCAL ]
- elif in6_ismsladdr(addr):
- cset = [ x for x in laddr if x[1] == IPV6_ADDR_SITELOCAL ]
- elif addr == '::' and plen == 0:
- cset = [ x for x in laddr if x[1] == IPV6_ADDR_GLOBAL ]
- cset = [ x[0] for x in cset ]
- cset.sort(key = cmp_to_key(cset_sort)) # Sort with global addresses first
- return cset
-
-def get_source_addr_from_candidate_set(dst, candidate_set):
- """
- This function implement a limited version of source address selection
- algorithm defined in section 5 of RFC 3484. The format is very different
- from that described in the document because it operates on a set
- of candidate source address for some specific route.
- """
-
- def scope_cmp(a, b):
- """
- Given two addresses, returns -1, 0 or 1 based on comparison of
- their scope
- """
- scope_mapper = {IPV6_ADDR_GLOBAL: 4,
- IPV6_ADDR_SITELOCAL: 3,
- IPV6_ADDR_LINKLOCAL: 2,
- IPV6_ADDR_LOOPBACK: 1}
- sa = in6_getscope(a)
- if sa == -1:
- sa = IPV6_ADDR_LOOPBACK
- sb = in6_getscope(b)
- if sb == -1:
- sb = IPV6_ADDR_LOOPBACK
-
- sa = scope_mapper[sa]
- sb = scope_mapper[sb]
-
- if sa == sb:
- return 0
- if sa > sb:
- return 1
- return -1
-
- def rfc3484_cmp(source_a, source_b):
- """
- The function implements a limited version of the rules from Source
- Address selection algorithm defined section of RFC 3484.
- """
-
- # Rule 1: Prefer same address
- if source_a == dst:
- return 1
- if source_b == dst:
- return 1
-
- # Rule 2: Prefer appropriate scope
- tmp = scope_cmp(source_a, source_b)
- if tmp == -1:
- if scope_cmp(source_a, dst) == -1:
- return 1
- else:
- return -1
- elif tmp == 1:
- if scope_cmp(source_b, dst) == -1:
- return 1
- else:
- return -1
-
- # Rule 3: cannot be easily implemented
- # Rule 4: cannot be easily implemented
- # Rule 5: does not make sense here
- # Rule 6: cannot be implemented
- # Rule 7: cannot be implemented
-
- # Rule 8: Longest prefix match
- tmp1 = in6_get_common_plen(source_a, dst)
- tmp2 = in6_get_common_plen(source_b, dst)
- if tmp1 > tmp2:
- return 1
- elif tmp2 > tmp1:
- return -1
- return 0
-
- if not candidate_set:
- # Should not happen
- return None
-
- candidate_set.sort(key=cmp_to_key(rfc3484_cmp), reverse=True)
-
- return candidate_set[0]
-
-
-def find_ifaddr2(addr, plen, laddr):
- dstAddrType = in6_getAddrType(addr)
-
- if dstAddrType == IPV6_ADDR_UNSPECIFIED: # Shouldn't happen as dst addr
- return None
-
- if dstAddrType == IPV6_ADDR_LOOPBACK:
- return None
-
- #tmp = [[]] + map(lambda (x,y,z): (in6_getAddrType(x), x, y, z), laddr)
- tmp = [[]] + map(lambda a: (in6_getAddrType(a[0]), a[0], a[1], a[2]), laddr)
- #def filterSameScope(l, t):
- # if (t[0] & dstAddrType & IPV6_ADDR_SCOPE_MASK) == 0:
- # l.append(t)
- # return l
- #sameScope = reduce(filterSameScope, tmp)
- sameScope = itertools.chain(*[ t for t in tmp if (t[0] & dstAddrType & IPV6_ADDR_SCOPE_MASK) == 0 ])
-
- l = len(sameScope)
- if l == 1: # Only one address for our scope
- return sameScope[0][1]
-
- elif l > 1: # Muliple addresses for our scope
- #stfAddr = filter(lambda x: x[0] & IPV6_ADDR_6TO4, sameScope)
- stfAddr = [ x for x in sameScope if x[0] & IPV6_ADDR_6TO4 ]
- #nativeAddr = filter(lambda x: not (x[0] & IPV6_ADDR_6TO4), sameScope)
- nativeAddr = [ x for x in sameScope if not (x[0] & IPV6_ADDR_6TO4) ]
-
- if not (dstAddrType & IPV6_ADDR_6TO4): # destination is not 6to4
- if len(nativeAddr) != 0:
- return nativeAddr[0][1]
- return stfAddr[0][1]
-
- else: # Destination is 6to4, try to use source 6to4 addr if any
- if len(stfAddr) != 0:
- return stfAddr[0][1]
- return nativeAddr[0][1]
- else:
- return None
-
-# Think before modify it : for instance, FE::1 does exist and is unicast
-# there are many others like that.
-# TODO : integrate Unique Local Addresses
-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 ((struct.unpack("B", naddr[0])[0] & 0xE0) == 0x20):
- if (((naddr[0]) & 0xE0) == 0x20):
- addrType = (IPV6_ADDR_UNICAST | IPV6_ADDR_GLOBAL)
- if naddr[:2] == b' \x02': # Mark 6to4 @
- addrType |= IPV6_ADDR_6TO4
- elif naddr[0] == 0xff: # multicast
- addrScope = paddr[3]
- if addrScope == '2':
- addrType = (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_MULTICAST)
- elif addrScope == 'e':
- addrType = (IPV6_ADDR_GLOBAL | IPV6_ADDR_MULTICAST)
- else:
- addrType = (IPV6_ADDR_GLOBAL | IPV6_ADDR_MULTICAST)
- elif ((naddr[0] == 0xfe) and ((int(paddr[2], 16) & 0xC) == 0x8)):
- addrType = (IPV6_ADDR_UNICAST | IPV6_ADDR_LINKLOCAL)
- elif paddr == "::1":
- addrType = IPV6_ADDR_LOOPBACK
- elif paddr == "::":
- addrType = IPV6_ADDR_UNSPECIFIED
- else:
- # Everything else is global unicast (RFC 3513)
- # Even old deprecated (RFC3879) Site-Local addresses
- addrType = (IPV6_ADDR_GLOBAL | IPV6_ADDR_UNICAST)
-
- return addrType
-
-def in6_mactoifaceid(mac, ulbit=None):
- """
- Compute the interface ID in modified EUI-64 format associated
- to the Ethernet address provided as input.
- value taken by U/L bit in the interface identifier is basically
- the reversed value of that in given MAC address it can be forced
- to a specific value by using optional 'ulbit' parameter.
- """
- if len(mac) != 17: return None
- m = "".join(mac.split(':'))
- if len(m) != 12: return None
- first = int(m[0:2], 16)
- if ulbit is None or not (ulbit == 0 or ulbit == 1):
- ulbit = [1,'-',0][first & 0x02]
- ulbit *= 2
- first = "%.02x" % ((first & 0xFD) | ulbit)
- eui64 = first + m[2:4] + ":" + m[4:6] + "FF:FE" + m[6:8] + ":" + m[8:12]
- return eui64.upper()
-
-def in6_ifaceidtomac(ifaceid): # TODO: finish commenting function behavior
- """
- Extract the mac address from provided iface ID. Iface ID is provided
- in printable format ("XXXX:XXFF:FEXX:XXXX", eventually compressed). None
- is returned on error.
- """
- try:
- ifaceid = inet_pton(socket.AF_INET6, "::"+ifaceid)[8:16]
- except:
- return None
- if ifaceid[3:5] != b'\xff\xfe':
- return None
- first = struct.unpack("B", ifaceid[:1])[0]
- ulbit = 2*[1,'-',0][first & 0x02]
- first = struct.pack("B", ((first & 0xFD) | ulbit))
- oui = first + ifaceid[1:3]
- end = ifaceid[5:]
- #l = map(lambda x: "%.02x" % struct.unpack("B", x)[0], list(oui+end))
- l = map(lambda x: "%.02x" % x, list(oui+end))
- return ":".join(l)
-
-def in6_addrtomac(addr):
- """
- Extract the mac address from provided address. None is returned
- on error.
- """
- mask = inet_pton(socket.AF_INET6, "::ffff:ffff:ffff:ffff")
- x = in6_and(mask, inet_pton(socket.AF_INET6, addr))
- ifaceid = inet_ntop(socket.AF_INET6, x)[2:]
- return in6_ifaceidtomac(ifaceid)
-
-def in6_addrtovendor(addr):
- """
- Extract the MAC address from a modified EUI-64 constructed IPv6
- address provided and use the IANA oui.txt file to get the vendor.
- The database used for the conversion is the one loaded by Scapy,
- based on Wireshark (/usr/share/wireshark/wireshark/manuf) None
- is returned on error, "UNKNOWN" if the vendor is unknown.
- """
- mac = in6_addrtomac(addr)
- if mac is None:
- return None
-
- res = conf.manufdb._get_manuf(mac)
- if len(res) == 17 and res.count(b':') != 5: # Mac address, i.e. unknown
- res = "UNKNOWN"
-
- return res
-
-def in6_getLinkScopedMcastAddr(addr, grpid=None, scope=2):
- """
- Generate a Link-Scoped Multicast Address as described in RFC 4489.
- Returned value is in printable notation.
-
- 'addr' parameter specifies the link-local address to use for generating
- Link-scoped multicast address IID.
-
- By default, the function returns a ::/96 prefix (aka last 32 bits of
- returned address are null). If a group id is provided through 'grpid'
- parameter, last 32 bits of the address are set to that value (accepted
- formats : '\x12\x34\x56\x78' or '12345678' or 0x12345678 or 305419896).
-
- By default, generated address scope is Link-Local (2). That value can
- be modified by passing a specific 'scope' value as an argument of the
- function. RFC 4489 only authorizes scope values <= 2. Enforcement
- is performed by the function (None will be returned).
-
- If no link-local address can be used to generate the Link-Scoped IPv6
- Multicast address, or if another error occurs, None is returned.
- """
- if not scope in [0, 1, 2]:
- return None
- try:
- if not in6_islladdr(addr):
- return None
- addr = inet_pton(socket.AF_INET6, addr)
- except:
- warning("in6_getLinkScopedMcastPrefix(): Invalid address provided")
- return None
-
- iid = addr[8:]
-
- if grpid is None:
- grpid = b'\x00\x00\x00\x00'
- else:
- if type(grpid) is str:
- grpid = grpid.encode('ascii')
- if type(grpid) is bytes:
- if len(grpid) == 8:
- try:
- grpid = int(grpid, 16) & 0xffffffff
- except:
- warning("in6_getLinkScopedMcastPrefix(): Invalid group id provided")
- return None
- elif len(grpid) == 4:
- try:
- grpid = struct.unpack("!I", grpid)[0]
- except:
- warning("in6_getLinkScopedMcastPrefix(): Invalid group id provided")
- return None
- grpid = struct.pack("!I", grpid)
-
- flgscope = struct.pack("B", 0xff & ((0x3 << 4) | scope))
- plen = b'\xff'
- res = b'\x00'
- a = b'\xff' + flgscope + res + plen + iid + grpid
-
- return inet_ntop(socket.AF_INET6, a)
-
-def in6_get6to4Prefix(addr):
- """
- Returns the /48 6to4 prefix associated with provided IPv4 address
- On error, None is returned. No check is performed on public/private
- status of the address
- """
- try:
- addr = inet_pton(socket.AF_INET, addr)
- addr = inet_ntop(socket.AF_INET6, b'\x20\x02'+addr+b'\x00'*10)
- except:
- return None
- return addr
-
-def in6_6to4ExtractAddr(addr):
- """
- Extract IPv4 address embbeded in 6to4 address. Passed address must be
- a 6to4 addrees. None is returned on error.
- """
- try:
- addr = inet_pton(socket.AF_INET6, addr)
- except:
- return None
- if addr[:2] != b" \x02":
- return None
- return inet_ntop(socket.AF_INET, addr[2:6])
-
-
-def in6_getLocalUniquePrefix():
- """
- Returns a pseudo-randomly generated Local Unique prefix. Function
- follows recommandation of Section 3.2.2 of RFC 4193 for prefix
- generation.
- """
- # Extracted from RFC 1305 (NTP) :
- # NTP timestamps are represented as a 64-bit unsigned fixed-point number,
- # in seconds relative to 0h on 1 January 1900. The integer part is in the
- # first 32 bits and the fraction part in the last 32 bits.
-
- # epoch = (1900, 1, 1, 0, 0, 0, 5, 1, 0)
- # x = time.time()
- # from time import gmtime, strftime, gmtime, mktime
- # delta = mktime(gmtime(0)) - mktime(self.epoch)
- # x = x-delta
-
- tod = time.time() # time of day. Will bother with epoch later
- i = int(tod)
- j = int((tod - i)*(2**32))
- tod = struct.pack("!II", i,j)
- # TODO: Add some check regarding system address gathering
- rawmac = get_if_raw_hwaddr(conf.iface6)
- mac = b":".join(map(lambda x: b"%.02x" % ord(x), list(rawmac)))
- # construct modified EUI-64 ID
- eui64 = inet_pton(socket.AF_INET6, '::' + in6_mactoifaceid(mac))[8:]
- import sha
- globalid = sha.new(tod+eui64).digest()[:5]
- return inet_ntop(socket.AF_INET6, b'\xfd' + globalid + b'\x00'*10)
-
-def in6_getRandomizedIfaceId(ifaceid, previous=None):
- """
- Implements the interface ID generation algorithm described in RFC 3041.
- The function takes the Modified EUI-64 interface identifier generated
- as described in RFC 4291 and an optional previous history value (the
- first element of the output of this function). If no previous interface
- identifier is provided, a random one is generated. The function returns
- a tuple containing the randomized interface identifier and the history
- value (for possible future use). Input and output values are provided in
- a "printable" format as depicted below.
-
- ex:
-
- >>> in6_getRandomizedIfaceId('20b:93ff:feeb:2d3')
- ('4c61:76ff:f46a:a5f3', 'd006:d540:db11:b092')
-
- >>> in6_getRandomizedIfaceId('20b:93ff:feeb:2d3',
- previous='d006:d540:db11:b092')
- ('fe97:46fe:9871:bd38', 'eeed:d79c:2e3f:62e')
- """
-
- s = []
- if previous is None:
- #d = b"".join(map(chr, range(256)))
- d = list(range(256))
- for i in range(8):
- s.append(random.choice(d))
- s = bytes(s)
- previous = s
- s = inet_pton(socket.AF_INET6, "::"+ifaceid)[8:] + previous
- import hashlib
- s = hashlib.md5(s).digest()
- s1,s2 = s[:8],s[8:]
- s1 = bytes([(s1[0]) | 0x04]) + s1[1:]
- s1 = inet_ntop(socket.AF_INET6, b"\xff"*8 + s1)[20:]
- s2 = inet_ntop(socket.AF_INET6, b"\xff"*8 + s2)[20:]
- return (s1, s2)
-
-
-_rfc1924map = [ '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E',
- 'F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T',
- 'U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i',
- 'j','k','l','m','n','o','p','q','r','s','t','u','v','w','x',
- 'y','z','!','#','$','%','&','(',')','*','+','-',';','<','=',
- '>','?','@','^','_','`','{','|','}','~' ]
-
-def in6_ctop(addr):
- """
- Convert an IPv6 address in Compact Representation Notation
- (RFC 1924) to printable representation ;-)
- Returns None on error.
- """
- #if len(addr) != 20 or not reduce(lambda x,y: x and y, map(lambda x: x in _rfc1924map, addr)):
- if len(addr) != 20 or not all(map(lambda x: x in _rfc1924map, addr)):
- return None
- i = 0
- for c in addr:
- j = _rfc1924map.index(c)
- i = 85*i + j
- res = []
- for j in range(4):
- res.append(struct.pack("!I", i%2**32))
- i = i//(2**32)
- res.reverse()
- return inet_ntop(socket.AF_INET6, b"".join(res))
-
-def in6_ptoc(addr):
- """
- Converts an IPv6 address in printable representation to RFC
- 1924 Compact Representation ;-)
- Returns None on error.
- """
- try:
- d=struct.unpack("!IIII", inet_pton(socket.AF_INET6, addr))
- except:
- return None
- res = 0
- m = [2**96, 2**64, 2**32, 1]
- for i in range(4):
- res += d[i]*m[i]
- rem = res
- res = []
- while rem:
- res.append(_rfc1924map[rem%85])
- rem = rem//85
- res.reverse()
- return "".join(res)
-
-
-def in6_isaddr6to4(x):
- """
- Return True if provided address (in printable format) is a 6to4
- address (being in 2002::/16).
- """
- x = inet_pton(socket.AF_INET6, x)
- return x[:2] == ' \x02'
-
-conf.teredoPrefix = "2001::" # old one was 3ffe:831f (it is a /32)
-conf.teredoServerPort = 3544
-
-def in6_isaddrTeredo(x):
- """
- Return True if provided address is a Teredo, meaning it is under
- the /32 conf.teredoPrefix prefix value (by default, 2001::).
- Otherwise, False is returned. Address must be passed in printable
- format.
- """
- our = inet_pton(socket.AF_INET6, x)[0:4]
- teredoPrefix = inet_pton(socket.AF_INET6, conf.teredoPrefix)[0:4]
- return teredoPrefix == our
-
-def teredoAddrExtractInfo(x):
- """
- Extract information from a Teredo address. Return value is
- a 4-tuple made of IPv4 address of Teredo server, flag value (int),
- mapped address (non obfuscated) and mapped port (non obfuscated).
- No specific checks are performed on passed address.
- """
- addr = inet_pton(socket.AF_INET6, x)
- server = inet_ntop(socket.AF_INET, addr[4:8])
- flag = struct.unpack("!H",addr[8:10])[0]
- mappedport = struct.unpack("!H",strxor(addr[10:12],b'\xff'*2))[0]
- mappedaddr = inet_ntop(socket.AF_INET, strxor(addr[12:16],b'\xff'*4))
- return server, flag, mappedaddr, mappedport
-
-def in6_iseui64(x):
- """
- Return True if provided address has an interface identifier part
- created in modified EUI-64 format (meaning it matches *::*:*ff:fe*:*).
- Otherwise, False is returned. Address must be passed in printable
- format.
- """
- eui64 = inet_pton(socket.AF_INET6, '::ff:fe00:0')
- x = in6_and(inet_pton(socket.AF_INET6, x), eui64)
- return x == eui64
-
-def in6_isanycast(x): # RFC 2526
- if in6_iseui64(x):
- s = '::fdff:ffff:ffff:ff80'
- packed_x = inet_pton(socket.AF_INET6, x)
- packed_s = inet_pton(socket.AF_INET6, s)
- x_and_s = in6_and(packed_x, packed_s)
- return x_and_s == packed_s
- else:
- # not EUI-64
- #| n bits | 121-n bits | 7 bits |
- #+---------------------------------+------------------+------------+
- #| subnet prefix | 1111111...111111 | anycast ID |
- #+---------------------------------+------------------+------------+
- # | interface identifier field |
- warning('in6_isanycast(): TODO not EUI-64')
- return 0
-
-def _in6_bitops(a1, a2, operator=0):
- a1 = struct.unpack('4I', a1)
- a2 = struct.unpack('4I', a2)
- fop = [ lambda x,y: x | y,
- lambda x,y: x & y,
- lambda x,y: x ^ y
- ]
- ret = map(fop[operator%len(fop)], a1, a2)
- t = b''.join(map(lambda x: struct.pack('I', x), ret))
- return t
-
-def in6_or(a1, a2):
- """
- Provides a bit to bit OR of provided addresses. They must be
- passed in network format. Return value is also an IPv6 address
- in network format.
- """
- return _in6_bitops(a1, a2, 0)
-
-def in6_and(a1, a2):
- """
- Provides a bit to bit AND of provided addresses. They must be
- passed in network format. Return value is also an IPv6 address
- in network format.
- """
- return _in6_bitops(a1, a2, 1)
-
-def in6_xor(a1, a2):
- """
- Provides a bit to bit XOR of provided addresses. They must be
- passed in network format. Return value is also an IPv6 address
- in network format.
- """
- return _in6_bitops(a1, a2, 2)
-
-def in6_cidr2mask(m):
- """
- Return the mask (bitstring) associated with provided length
- value. For instance if function is called on 48, return value is
- '\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'.
-
- """
- if m > 128 or m < 0:
- raise Scapy_Exception("value provided to in6_cidr2mask outside [0, 128] domain (%d)" % m)
-
- t = []
- for i in range(0, 4):
- t.append(max(0, 2**32 - 2**(32-min(32, m))))
- m -= 32
-
- return b"".join([ struct.pack('!I', i) for i in t ])
-
-def in6_getnsma(a):
- """
- Return link-local solicited-node multicast address for given
- address. Passed address must be provided in network format.
- Returned value is also in network format.
- """
-
- r = in6_and(a, inet_pton(socket.AF_INET6, '::ff:ffff'))
- r = in6_or(inet_pton(socket.AF_INET6, 'ff02::1:ff00:0'), r)
- return r
-
-def in6_getnsmac(a): # return multicast Ethernet address associated with multicast v6 destination
- """
- Return the multicast mac address associated with provided
- IPv6 address. Passed address must be in network format.
- """
-
- a = struct.unpack('16B', a)[-4:]
- mac = '33:33:'
- mac += (':'.join(map(lambda x: '%.2x' %x, a)))
- return mac
-
-def in6_getha(prefix):
- """
- Return the anycast address associated with all home agents on a given
- subnet.
- """
- r = in6_and(inet_pton(socket.AF_INET6, prefix), in6_cidr2mask(64))
- r = in6_or(r, inet_pton(socket.AF_INET6, '::fdff:ffff:ffff:fffe'))
- return inet_ntop(socket.AF_INET6, r)
-
-def in6_ptop(s):
- """
- Normalizes IPv6 addresses provided in printable format, returning the
- same address in printable format. (2001:0db8:0:0::1 -> 2001:db8::1)
- """
- return inet_ntop(socket.AF_INET6, inet_pton(socket.AF_INET6, s))
-
-def in6_isincluded(addr, prefix, plen):
- """
- Returns True when 'addr' belongs to prefix/plen. False otherwise.
- """
- temp = inet_pton(socket.AF_INET6, addr)
- pref = in6_cidr2mask(plen)
- zero = inet_pton(socket.AF_INET6, prefix)
- return zero == in6_and(temp, pref)
-
-def in6_isdocaddr(s):
- """
- Returns True if provided address in printable format belongs to
- 2001:db8::/32 address space reserved for documentation (as defined
- in RFC 3849).
- """
- return in6_isincluded(s, '2001:db8::', 32)
-
-def in6_islladdr(s):
- """
- Returns True if provided address in printable format belongs to
- _allocated_ link-local unicast address space (fe80::/10)
- """
- return in6_isincluded(s, 'fe80::', 10)
-
-def in6_issladdr(s):
- """
- Returns True if provided address in printable format belongs to
- _allocated_ site-local address space (fec0::/10). This prefix has
- been deprecated, address being now reserved by IANA. Function
- will remain for historic reasons.
- """
- return in6_isincluded(s, 'fec0::', 10)
-
-def in6_isuladdr(s):
- """
- Returns True if provided address in printable format belongs to
- Unique local address space (fc00::/7).
- """
- return in6_isincluded(s, '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(s):
- """
- Returns True if provided address in printable format belongs to
- _allocated_ global address space (2000::/3). Please note that,
- Unique Local addresses (FC00::/7) are not part of global address
- space, and won't match.
- """
- return in6_isincluded(s, '2000::', 3)
-
-def in6_ismaddr(s):
- """
- Returns True if provided address in printable format belongs to
- allocated Multicast address space (ff00::/8).
- """
- return in6_isincluded(s, 'ff00::', 8)
-
-def in6_ismnladdr(s):
- """
- Returns True if address belongs to node-local multicast address
- space (ff01::/16) as defined in RFC
- """
- return in6_isincluded(s, 'ff01::', 16)
-
-def in6_ismgladdr(s):
- """
- Returns True if address belongs to global multicast address
- space (ff0e::/16).
- """
- return in6_isincluded(s, 'ff0e::', 16)
-
-def in6_ismlladdr(s):
- """
- Returns True if address belongs to link-local multicast address
- space (ff02::/16)
- """
- return in6_isincluded(s, 'ff02::', 16)
-
-def in6_ismsladdr(s):
- """
- Returns True if address belongs to site-local multicast address
- space (ff05::/16). Site local address space has been deprecated.
- Function remains for historic reasons.
- """
- return in6_isincluded(s, 'ff05::', 16)
-
-def in6_isaddrllallnodes(s):
- """
- Returns True if address is the link-local all-nodes multicast
- address (ff02::1).
- """
- return (inet_pton(socket.AF_INET6, "ff02::1") ==
- inet_pton(socket.AF_INET6, s))
-
-def in6_isaddrllallservers(s):
- """
- Returns True if address is the link-local all-servers multicast
- address (ff02::2).
- """
- return (inet_pton(socket.AF_INET6, "ff02::2") ==
- inet_pton(socket.AF_INET6, s))
-
-def in6_getscope(addr):
- """
- Returns the scope of the address.
- """
- if in6_isgladdr(addr) or in6_isuladdr(addr):
- scope = IPV6_ADDR_GLOBAL
- elif in6_islladdr(addr):
- scope = IPV6_ADDR_LINKLOCAL
- elif in6_issladdr(addr):
- scope = IPV6_ADDR_SITELOCAL
- elif in6_ismaddr(addr):
- if in6_ismgladdr(addr):
- scope = IPV6_ADDR_GLOBAL
- elif in6_ismlladdr(addr):
- scope = IPV6_ADDR_LINKLOCAL
- elif in6_ismsladdr(addr):
- scope = IPV6_ADDR_SITELOCAL
- elif in6_ismnladdr(addr):
- scope = IPV6_ADDR_LOOPBACK
- else:
- scope = -1
- elif addr == '::1':
- scope = IPV6_ADDR_LOOPBACK
- else:
- scope = -1
- return scope
-
-def in6_get_common_plen(a, b):
- """
- Return common prefix length of IPv6 addresses a and b.
- """
- def matching_bits(byte1, byte2):
- for i in range(8):
- cur_mask = 0x80 >> i
- if (byte1 & cur_mask) != (byte2 & cur_mask):
- return i
- return 8
-
- tmpA = inet_pton(socket.AF_INET6, a)
- tmpB = inet_pton(socket.AF_INET6, b)
- for i in range(16):
- #mbits = matching_bits(ord(tmpA[i]), ord(tmpB[i]))
- mbits = matching_bits((tmpA[i]), (tmpB[i]))
- if mbits != 8:
- return 8*i + mbits
- return 128