def in6_isaddrllallservers(str): """ 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, str))
def _in6_getifaddr(ifname): """ Returns a list of IPv6 addresses configured on the interface ifname. """ # Get the output of ifconfig try: f = os.popen("%s %s" % (conf.prog.ifconfig, ifname)) except OSError: log_interactive.warning("Failed to execute ifconfig.") return [] # Iterate over lines and extract IPv6 addresses ret = [] for line in f: if "inet6" in line: addr = line.rstrip().split(None, 2)[1] # The second element is the IPv6 address # noqa: E501 else: continue if '%' in line: # Remove the interface identifier if present addr = addr.split("%", 1)[0] # Check if it is a valid IPv6 address try: inet_pton(socket.AF_INET6, addr) except (socket.error, ValueError): continue # Get the scope and keep the address scope = in6_getscope(addr) ret.append((addr, scope, ifname)) return ret
def in6_isaddrllallnodes(str): """ 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, str))
def parse_args(self, server="127.0.0.1", sport=4433, mycert=None, mykey=None, preferred_ciphersuite=None, client_auth=False, is_echo_server=True, max_client_idle_time=60, **kargs): super(TLSServerAutomaton, self).parse_args(mycert=mycert, mykey=mykey, **kargs) try: if ':' in server: inet_pton(socket.AF_INET6, server) else: inet_pton(socket.AF_INET, server) tmp = socket.getaddrinfo(server, sport) except: tmp = socket.getaddrinfo(socket.getfqdn(server), sport) self.serversocket = None self.ip_family = tmp[0][0] self.local_ip = tmp[0][4][0] self.local_port = sport self.remote_ip = None self.remote_port = None self.preferred_ciphersuite = preferred_ciphersuite self.client_auth = client_auth self.is_echo_server = is_echo_server self.max_client_idle_time = max_client_idle_time
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_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_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_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_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 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_isaddrTeredo(x): # type: (str) -> bool """ 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 in6_iseui64(x): # type: (str) -> bool """ 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') bx = in6_and(inet_pton(socket.AF_INET6, x), eui64) return bx == eui64
def in6_getnsma(a): # type: (bytes) -> bytes """ 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 parse_args(self, server="127.0.0.1", dport=4433, server_name=None, mycert=None, mykey=None, client_hello=None, version=None, data=None, **kargs): super(TLSClientAutomaton, self).parse_args(mycert=mycert, mykey=mykey, **kargs) tmp = socket.getaddrinfo(server, dport) self.remote_name = None try: if ':' in server: inet_pton(socket.AF_INET6, server) else: inet_pton(socket.AF_INET, server) except: self.remote_name = socket.getfqdn(server) if self.remote_name != server: tmp = socket.getaddrinfo(self.remote_name, dport) if server_name: self.remote_name = server_name self.remote_family = tmp[0][0] self.remote_ip = tmp[0][4][0] self.remote_port = dport self.local_ip = None self.local_port = None self.socket = None self.client_hello = client_hello self.advertised_tls_version = None if version: v = _tls_version_options.get(version, None) if not v: self.vprint("Unrecognized TLS version option.") else: self.advertised_tls_version = v self.linebreak = False if isinstance(data, bytes): self.data_to_send = [data] elif isinstance(data, six.string_types): self.data_to_send = [raw(data)] elif isinstance(data, list): self.data_to_send = list(raw(d) for d in reversed(data)) else: self.data_to_send = []
def parse_args(self, server="127.0.0.1", dport=4433, server_name=None, mycert=None, mykey=None, client_hello=None, version=None, data=None, **kargs): super(TLSClientAutomaton, self).parse_args(mycert=mycert, mykey=mykey, **kargs) tmp = socket.getaddrinfo(server, dport) self.remote_name = None try: if ':' in server: inet_pton(socket.AF_INET6, server) else: inet_pton(socket.AF_INET, server) except: self.remote_name = socket.getfqdn(server) if self.remote_name != server: tmp = socket.getaddrinfo(self.remote_name, dport) if server_name: self.remote_name = server_name self.remote_family = tmp[0][0] self.remote_ip = tmp[0][4][0] self.remote_port = dport self.local_ip = None self.local_port = None self.socket = None self.client_hello = client_hello self.advertised_tls_version = None if version: v = _tls_version_options.get(version, None) if not v: self.vprint("Unrecognized TLS version option.") else: self.advertised_tls_version = v self.linebreak = False if isinstance(data, bytes): self.data_to_send = [data] elif isinstance(data, six.string_types): self.data_to_send = [raw(data)] elif isinstance(data, list): self.data_to_send = list(raw(d) for d in reversed(data)) else: self.data_to_send = []
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): addrType = (IPV6_ADDR_UNICAST | IPV6_ADDR_GLOBAL) if naddr[:2] == b' \x02': # Mark 6to4 @ addrType |= IPV6_ADDR_6TO4 elif orb(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 ((orb(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_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 compressDestinyAddr(self, ipv6): tmp_ip = inet_pton(socket.AF_INET6, ipv6.dst) if self.m == 0 and self.dac == 0: if self.dam == 0x0: tmp_ip = tmp_ip elif self.dam == 0x1: tmp_ip = b"\x00" * 8 + tmp_ip[8:16] elif self.dam == 0x2: tmp_ip = b"\x00" * 14 + tmp_ip[14:16] elif self.m == 0 and self.dac == 1: if self.dam == 0x1: tmp_ip = b"\x00" * 8 + tmp_ip[8:16] elif self.dam == 0x2: tmp_ip = b"\x00" * 14 + tmp_ip[14:16] elif self.m == 1 and self.dac == 0: if self.dam == 0x1: tmp_ip = b"\x00" * 10 + tmp_ip[1:2] + tmp_ip[11:16] elif self.dam == 0x2: tmp_ip = b"\x00" * 12 + tmp_ip[1:2] + tmp_ip[13:16] elif self.dam == 0x3: tmp_ip = b"\x00" * 15 + tmp_ip[15:16] elif self.m == 1 and self.dac == 1: raise Exception('Unimplemented') self.destinyAddr = inet_ntop(socket.AF_INET6, tmp_ip)
def decompressSourceAddr(self, packet): # https://tools.ietf.org/html/rfc6282#section-3.1.1 try: tmp_ip = inet_pton(socket.AF_INET6, self.src) except socket.error: tmp_ip = b"\x00" * 16 if self.sac == 0: if self.sam == 0x0: # Full address is carried in-line pass elif self.sam == 0x1: tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[16 - source_addr_size(self):16] # noqa: E501 elif self.sam == 0x2: tmp = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00" tmp_ip = tmp + tmp_ip[16 - source_addr_size(self):16] elif self.sam == 0x3: # Taken from encapsulating header tmp_ip = _extract_upperaddress(self, source=True) else: # self.sac == 1: if self.sam == 0x0: # Unspecified address :: pass elif self.sam == 0x1: # should use context IID pass elif self.sam == 0x2: # should use context IID tmp = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00" tmp_ip = tmp + tmp_ip[16 - source_addr_size(self):16] elif self.sam == 0x3: # should use context IID tmp_ip = LINK_LOCAL_PREFIX[0:8] + b"\x00" * 8 self.src = inet_ntop(socket.AF_INET6, tmp_ip) return self.src
def compressDestAddr(self, ipv6): # https://tools.ietf.org/html/rfc6282#section-3.1.1 tmp_ip = inet_pton(socket.AF_INET6, ipv6.dst) if self.m == 0 and self.dac == 0: if self.dam == 0x0: pass elif self.dam == 0x1: tmp_ip = b"\x00" * 8 + tmp_ip[8:16] elif self.dam == 0x2: tmp_ip = b"\x00" * 14 + tmp_ip[14:16] elif self.m == 0 and self.dac == 1: if self.dam == 0x1: tmp_ip = b"\x00" * 8 + tmp_ip[8:16] elif self.dam == 0x2: tmp_ip = b"\x00" * 14 + tmp_ip[14:16] elif self.m == 1 and self.dac == 0: if self.dam == 0x0: pass if self.dam == 0x1: tmp_ip = b"\x00" * 10 + tmp_ip[1:2] + tmp_ip[11:16] elif self.dam == 0x2: tmp_ip = b"\x00" * 12 + tmp_ip[1:2] + tmp_ip[13:16] elif self.dam == 0x3: tmp_ip = b"\x00" * 15 + tmp_ip[15:16] elif self.m == 1 and self.dac == 1: if self.dam == 0: tmp_ip = b"\x00" * 10 + tmp_ip[1:3] + tmp_ip[12:16] self.dst = inet_ntop(socket.AF_INET6, tmp_ip)
def in6_getAddrType(addr): # type: (str) -> int 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): addrType = (IPV6_ADDR_UNICAST | IPV6_ADDR_GLOBAL) if naddr[:2] == b' \x02': # Mark 6to4 @ addrType |= IPV6_ADDR_6TO4 elif orb(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 ((orb(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 compressDestinyAddr(self, ipv6): tmp_ip = inet_pton(socket.AF_INET6, ipv6.dst) if self.m == 0 and self.dac == 0: if self.dam == 0x0: pass elif self.dam == 0x1: tmp_ip = b"\x00" * 8 + tmp_ip[8:16] elif self.dam == 0x2: tmp_ip = b"\x00" * 14 + tmp_ip[14:16] elif self.m == 0 and self.dac == 1: if self.dam == 0x1: tmp_ip = b"\x00" * 8 + tmp_ip[8:16] elif self.dam == 0x2: tmp_ip = b"\x00" * 14 + tmp_ip[14:16] elif self.m == 1 and self.dac == 0: if self.dam == 0x1: tmp_ip = b"\x00" * 10 + tmp_ip[1:2] + tmp_ip[11:16] elif self.dam == 0x2: tmp_ip = b"\x00" * 12 + tmp_ip[1:2] + tmp_ip[13:16] elif self.dam == 0x3: tmp_ip = b"\x00" * 15 + tmp_ip[15:16] elif self.m == 1 and self.dac == 1: raise Exception('Unimplemented') self.destinyAddr = inet_ntop(socket.AF_INET6, tmp_ip)
def decompressSourceAddr(self, packet): try: tmp_ip = inet_pton(socket.AF_INET6, self.sourceAddr) except socket.error: tmp_ip = b"\x00" * 16 if self.sac == 0: if self.sam == 0x0: pass elif self.sam == 0x1: tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[16 - source_addr_mode2(self):16] # noqa: E501 elif self.sam == 0x2: tmp = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00" tmp_ip = tmp + tmp_ip[16 - source_addr_mode2(self):16] elif self.sam == 0x3: # EXTRACT ADDRESS FROM Dot15d4 tmp_ip = _extract_dot15d4address(self, source=True) else: warning("Unknown source address compression mode !") else: # self.sac == 1: if self.sam == 0x0: pass elif self.sam == 0x2: # TODO: take context IID tmp = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00" tmp_ip = tmp + tmp_ip[16 - source_addr_mode2(self):16] elif self.sam == 0x3: tmp_ip = LINK_LOCAL_PREFIX[0:8] + b"\x00" * 8 # TODO: CONTEXT ID # noqa: E501 else: raise Exception('Unimplemented') self.sourceAddr = inet_ntop(socket.AF_INET6, tmp_ip) return self.sourceAddr
def in6_getLocalUniquePrefix(): # type: () -> str """ Returns a pseudo-randomly generated Local Unique prefix. Function follows recommendation 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)) btod = struct.pack("!II", i, j) mac = RandMAC() # construct modified EUI-64 ID eui64 = inet_pton(socket.AF_INET6, '::' + in6_mactoifaceid(mac))[8:] import hashlib globalid = hashlib.sha1(btod + eui64).digest()[:5] return inet_ntop(socket.AF_INET6, b'\xfd' + globalid + b'\x00' * 10)
def in6_ifaceidtomac(ifaceid_s): # type: (str) -> Optional[str] """ 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: # Set ifaceid to a binary form ifaceid = inet_pton(socket.AF_INET6, "::" + ifaceid_s)[8:16] except Exception: return None if ifaceid[3:5] != b'\xff\xfe': # Check for burned-in MAC address return None # Unpacking and converting first byte of faceid to MAC address equivalent first = struct.unpack("B", ifaceid[:1])[0] ulbit = 2 * [1, '-', 0][first & 0x02] first = struct.pack("B", ((first & 0xFD) | ulbit)) # Split into two vars to remove the \xff\xfe bytes oui = first + ifaceid[1:3] end = ifaceid[5:] # Convert and reconstruct into a MAC Address mac_bytes = ["%.02x" % orb(x) for x in list(oui + end)] return ":".join(mac_bytes)
def add_ndp_reply_entry(self, target_addr, target_mac): target_addr = inet_pton(socket.AF_INET6, target_addr) target_mac = mac_to_binary(target_mac) mk = [self.Exact("hdr.ndp.target_addr", target_addr)] self.send_request_add_entry_to_action( "FabricIngress.ndp_reply", mk, "FabricIngress.ndp_advertisement", [("router_mac", target_mac)])
def in6_getLocalUniquePrefix(): """ Returns a pseudo-randomly generated Local Unique prefix. Function follows recommendation 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) mac = RandMAC() # construct modified EUI-64 ID eui64 = inet_pton(socket.AF_INET6, '::' + in6_mactoifaceid(mac))[8:] import hashlib globalid = hashlib.sha1(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 = b"" if previous is None: d = b"".join(chb(x) for x in range(256)) for _ in range(8): s += chb(random.choice(d)) 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 = chb(orb(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)
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] == b' \x02'
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] == b' \x02'
def in6_ptop(str): # type: (str) -> str """ 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, str))
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 = b"" if previous is None: d = b"".join(chb(x) for x in range(256)) for _ in range(8): s += chb(random.choice(d)) 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 = chb(orb(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)
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 decompressSourceAddr(self, packet): try: tmp_ip = inet_pton(socket.AF_INET6, self.sourceAddr) except socket.error: tmp_ip = b"\x00" * 16 if self.sac == 0: if self.sam == 0x0: pass elif self.sam == 0x1: tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[16 - source_addr_mode2(self):16] # noqa: E501 elif self.sam == 0x2: tmp = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00" tmp_ip = tmp + tmp_ip[16 - source_addr_mode2(self):16] elif self.sam == 0x3: # EXTRACT ADDRESS FROM Dot15d4 tmp_ip = _extract_dot15d4address(self, source=True) else: warning("Unknown source address compression mode !") else: # self.sac == 1: if self.sam == 0x0: pass elif self.sam == 0x2: # TODO: take context IID tmp = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00" tmp_ip = tmp + tmp_ip[16 - source_addr_mode2(self):16] elif self.sam == 0x3: tmp_ip = LINK_LOCAL_PREFIX[0:8] + b"\x00" * 8 # TODO: CONTEXT ID # noqa: E501 else: raise Exception('Unimplemented') self.sourceAddr = inet_ntop(socket.AF_INET6, tmp_ip) return self.sourceAddr
def genNdpNsPkt(src_mac, src_ip, target_ip): nsma = in6_getnsma(inet_pton(socket.AF_INET6, target_ip)) d = inet_ntop(socket.AF_INET6, nsma) dm = in6_getnsmac(nsma) p = Ether(dst=dm) / IPv6(dst=d, src=src_ip, hlim=255) p /= ICMPv6ND_NS(tgt=target_ip) p /= ICMPv6NDOptSrcLLAddr(lladdr=src_mac) return p
def decompressDestAddr(self, packet): # https://tools.ietf.org/html/rfc6282#section-3.1.1 try: tmp_ip = inet_pton(socket.AF_INET6, self.dst) except socket.error: tmp_ip = b"\x00" * 16 if self.m == 0 and self.dac == 0: if self.dam == 0: # Address fully carried pass elif self.dam == 1: tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[-8:] elif self.dam == 2: tmp_ip = LINK_LOCAL_PREFIX[ 0:8] + b"\x00\x00\x00\xff\xfe\x00" + tmp_ip[ -2:] # noqa: E501 elif self.dam == 3: tmp_ip = _extract_upperaddress(self, source=False) elif self.m == 0 and self.dac == 1: if self.dam == 0: # reserved pass elif self.dam == 0x3: # should use context IID + encapsulating header tmp_ip = _extract_upperaddress(self, source=False) elif self.dam not in [0x1, 0x2]: # https://tools.ietf.org/html/rfc6282#page-9 # Should use context information: unimplemented pass elif self.m == 1 and self.dac == 0: if self.dam == 0: # Address fully carried pass elif self.dam == 1: tmp = b"\xff" + chb(tmp_ip[16 - dest_addr_size(self)]) tmp_ip = tmp + b"\x00" * 9 + tmp_ip[-5:] elif self.dam == 2: tmp = b"\xff" + chb(tmp_ip[16 - dest_addr_size(self)]) tmp_ip = tmp + b"\x00" * 11 + tmp_ip[-3:] else: # self.dam == 3: tmp_ip = b"\xff\x02" + b"\x00" * 13 + tmp_ip[-1:] elif self.m == 1 and self.dac == 1: if self.dam == 0x0: # https://tools.ietf.org/html/rfc6282#page-10 # https://github.com/wireshark/wireshark/blob/f54611d1104d85a425e52c7318c522ed249916b6/epan/dissectors/packet-6lowpan.c#L2149-L2166 # Format: ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX # P and L should be retrieved from context P = b"\x00" * 16 L = b"\x00" X = tmp_ip[-6:] tmp_ip = b"\xff" + X[:2] + L + P[:8] + X[2:6] else: # all the others values: reserved pass self.dst = inet_ntop(socket.AF_INET6, tmp_ip) return self.dst
def parse_args(self, server="127.0.0.1", sport=4433, mycert=None, mykey=None, preferred_ciphersuite=None, client_auth=False, is_echo_server=True, max_client_idle_time=60, curve=None, cookie=False, psk=None, psk_mode=None, **kargs): super(TLSServerAutomaton, self).parse_args(mycert=mycert, mykey=mykey, **kargs) try: if ':' in server: inet_pton(socket.AF_INET6, server) else: inet_pton(socket.AF_INET, server) tmp = socket.getaddrinfo(server, sport) except Exception: tmp = socket.getaddrinfo(socket.getfqdn(server), sport) self.serversocket = None self.ip_family = tmp[0][0] self.local_ip = tmp[0][4][0] self.local_port = sport self.remote_ip = None self.remote_port = None self.preferred_ciphersuite = preferred_ciphersuite self.client_auth = client_auth self.is_echo_server = is_echo_server self.max_client_idle_time = max_client_idle_time self.curve = None self.cookie = cookie self.psk_secret = psk self.psk_mode = psk_mode for (group_id, ng) in _tls_named_groups.items(): if ng == curve: self.curve = group_id
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(orb(tmpA[i]), orb(tmpB[i])) if mbits != 8: return 8 * i + mbits return 128
def in6_isllsnmaddr(str): """ Return True if provided address is a link-local solicited node multicast address, i.e. belongs to ff02::1:ff00:0/104. False is returned otherwise. """ temp = in6_and(b"\xff" * 13 + b"\x00" * 3, inet_pton(socket.AF_INET6, str)) temp2 = b'\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\x00\x00\x00' return temp == temp2
def in6_isllsnmaddr(str): """ Return True if provided address is a link-local solicited node multicast address, i.e. belongs to ff02::1:ff00:0/104. False is returned otherwise. """ temp = in6_and(b"\xff" * 13 + b"\x00" * 3, inet_pton(socket.AF_INET6, str)) temp2 = b'\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\x00\x00\x00' return temp == temp2
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 : b'\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 scope not in [0, 1, 2]: return None try: if not in6_islladdr(addr): return None addr = inet_pton(socket.AF_INET6, addr) except Exception: warning("in6_getLinkScopedMcastPrefix(): Invalid address provided") return None iid = addr[8:] if grpid is None: grpid = b'\x00\x00\x00\x00' else: if isinstance(grpid, (bytes, str)): if len(grpid) == 8: try: grpid = int(grpid, 16) & 0xffffffff except Exception: warning("in6_getLinkScopedMcastPrefix(): Invalid group id provided") # noqa: E501 return None elif len(grpid) == 4: try: grpid = struct.unpack("!I", grpid)[0] except Exception: warning("in6_getLinkScopedMcastPrefix(): Invalid group id provided") # noqa: E501 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_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 : b'\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 scope not in [0, 1, 2]: return None try: if not in6_islladdr(addr): return None addr = inet_pton(socket.AF_INET6, addr) except Exception: warning("in6_getLinkScopedMcastPrefix(): Invalid address provided") return None iid = addr[8:] if grpid is None: grpid = b'\x00\x00\x00\x00' else: if isinstance(grpid, (bytes, str)): if len(grpid) == 8: try: grpid = int(grpid, 16) & 0xffffffff except Exception: warning("in6_getLinkScopedMcastPrefix(): Invalid group id provided") # noqa: E501 return None elif len(grpid) == 4: try: grpid = struct.unpack("!I", grpid)[0] except Exception: warning("in6_getLinkScopedMcastPrefix(): Invalid group id provided") # noqa: E501 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_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(orb(tmpA[i]), orb(tmpB[i])) if mbits != 8: return 8 * i + mbits return 128
def get_if_raw_addr6(iff): """ Returns the main global unicast address associated with provided interface, in network format. If no global address is found, None is returned. """ ip6= get_if_addr6(iff) if ip6 is not None: return inet_pton(socket.AF_INET6, ip6) return None
def get_if_raw_addr6(iff): """ Returns the main global unicast address associated with provided interface, in network format. If no global address is found, None is returned. """ ip6= get_if_addr6(iff) if ip6 is not None: return inet_pton(socket.AF_INET6, ip6) return None
def __init__(self, net): self.repr = net tmp = net.split('/') + ["128"] if not self.ip_regex.match(net): tmp[0] = socket.getaddrinfo(tmp[0], None, socket.AF_INET6)[0][-1][0] # noqa: E501 netmask = int(tmp[1]) self.net = inet_pton(socket.AF_INET6, tmp[0]) self.mask = in6_cidr2mask(netmask) self.plen = netmask
def __init__(self, net): self.repr = net tmp = net.split('/') + ["128"] if not self.ip_regex.match(net): tmp[0] = socket.getaddrinfo(tmp[0], None, socket.AF_INET6)[0][-1][0] # noqa: E501 netmask = int(tmp[1]) self.net = inet_pton(socket.AF_INET6, tmp[0]) self.mask = in6_cidr2mask(netmask) self.plen = netmask
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 Exception: return None return addr
def in6_get6to4Prefix(addr): # type: (str) -> Optional[str] """ 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: baddr = inet_pton(socket.AF_INET, addr) return inet_ntop(socket.AF_INET6, b'\x20\x02' + baddr + b'\x00' * 10) except Exception: return None
def in6_6to4ExtractAddr(addr): """ Extract IPv4 address embedded in 6to4 address. Passed address must be a 6to4 address. None is returned on error. """ try: addr = inet_pton(socket.AF_INET6, addr) except Exception: return None if addr[:2] != b" \x02": return None return inet_ntop(socket.AF_INET, addr[2:6])
def in6_6to4ExtractAddr(addr): """ Extract IPv4 address embedded in 6to4 address. Passed address must be a 6to4 address. None is returned on error. """ try: addr = inet_pton(socket.AF_INET6, addr) except Exception: return None if addr[:2] != b" \x02": return None return inet_ntop(socket.AF_INET, addr[2:6])
def i2m(self, pkt, s): if pkt.type == 1: # A if s: s = inet_pton(socket.AF_INET, s) elif pkt.type in [2, 3, 4, 5, 12]: # NS, MD, MF, CNAME, PTR s = DNSStrField("", "").i2m(None, s) elif pkt.type == 16: # TXT ret_s = b"" for text in s: # The initial string must be split into a list of strings # prepended with theirs sizes. while len(text) >= 255: ret_s += b"\xff" + text[:255] text = text[255:] # The remaining string is less than 255 bytes long if len(text): ret_s += struct.pack("!B", len(text)) + raw(text) s = ret_s elif pkt.type == 28: # AAAA if s: s = inet_pton(socket.AF_INET6, s) return s
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 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 decompressDestAddr(self): if not self.dp and not self.di: # Prefix & Interface return self.dst elif not self.di: # Only interface addr = inet_pton(socket.AF_INET6, self.dst)[-8:] addr = LINK_LOCAL_PREFIX[:8] + addr else: # Interface not provided addr = _extract_upperaddress(self, source=False) self.dst = inet_ntop(socket.AF_INET6, addr) return self.dst
def i2m(self, pkt, s): if pkt.type == 1: # A if s: s = inet_pton(socket.AF_INET, s) elif pkt.type in [2, 3, 4, 5, 12]: # NS, MD, MF, CNAME, PTR s = DNSStrField("", "").i2m(None, s) elif pkt.type == 16: # TXT ret_s = b"" for text in s: # The initial string must be split into a list of strings # prepended with theirs sizes. while len(text) >= 255: ret_s += b"\xff" + text[:255] text = text[255:] # The remaining string is less than 255 bytes long if len(text): ret_s += struct.pack("!B", len(text)) + raw(text) s = ret_s elif pkt.type == 28: # AAAA if s: s = inet_pton(socket.AF_INET6, s) return s
def __init__(self, net): # type: (str) -> None self.repr = net tmp = net.split('/') + ["128"] if not self.ip_regex.match(net): tmp[0] = socket.getaddrinfo( tmp[0], None, socket.AF_INET6)[0][-1][0] # noqa: E501 netmask = int(tmp[1]) self.net = inet_pton(socket.AF_INET6, tmp[0]) self.mask = in6_cidr2mask(netmask) self.plen = netmask self.parsed = [] # type: List[Tuple[int, int]]
def ifchange(self, iff, addr): the_addr, the_plen = (addr.split("/") + ["128"])[:2] the_plen = int(the_plen) naddr = inet_pton(socket.AF_INET6, the_addr) nmask = in6_cidr2mask(the_plen) the_net = inet_ntop(socket.AF_INET6, in6_and(nmask, naddr)) for i, route in enumerate(self.routes): net, plen, gw, iface, addr, metric = route if iface != iff: continue if gw == '::': self.routes[i] = (the_net, the_plen, gw, iface, [the_addr], metric) # noqa: E501 else: self.routes[i] = (net, plen, gw, iface, [the_addr], metric) self.invalidate_cache() conf.netcache.in6_neighbor.flush()
def decompressDestinyAddr(self, packet): try: tmp_ip = inet_pton(socket.AF_INET6, self.destinyAddr) except socket.error: tmp_ip = b"\x00" * 16 if self.m == 0 and self.dac == 0: if self.dam == 0: pass elif self.dam == 1: tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[-8:] elif self.dam == 2: tmp_ip = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00" + tmp_ip[-2:] # noqa: E501 elif self.dam == 3: # TODO May need some extra changes, we are copying # (self.m == 0 and self.dac == 1) tmp_ip = _extract_dot15d4address(self, source=False) elif self.m == 0 and self.dac == 1: if self.dam == 0: raise Exception('Reserved') elif self.dam == 0x3: tmp_ip = _extract_dot15d4address(self, source=False) elif self.dam not in [0x1, 0x2]: warning("Unknown destiny address compression mode !") elif self.m == 1 and self.dac == 0: if self.dam == 0: raise Exception("unimplemented") elif self.dam == 1: tmp = b"\xff" + chb(tmp_ip[16 - destiny_addr_mode(self)]) tmp_ip = tmp + b"\x00" * 9 + tmp_ip[-5:] elif self.dam == 2: tmp = b"\xff" + chb(tmp_ip[16 - destiny_addr_mode(self)]) tmp_ip = tmp + b"\x00" * 11 + tmp_ip[-3:] else: # self.dam == 3: tmp_ip = b"\xff\x02" + b"\x00" * 13 + tmp_ip[-1:] elif self.m == 1 and self.dac == 1: if self.dam == 0x0: raise Exception("Unimplemented: I didn't understand the 6lowpan specification") # noqa: E501 else: # all the others values raise Exception("Reserved value by specification.") self.destinyAddr = inet_ntop(socket.AF_INET6, tmp_ip) return self.destinyAddr
def ifadd(self, iff, addr): """ Add an interface 'iff' with provided address into routing table. Ex: ifadd('eth0', '2001:bd8:cafe:1::1/64') will add following entry into # noqa: E501 Scapy6 internal routing table: Destination Next Hop iface Def src @ Metric 2001:bd8:cafe:1::/64 :: eth0 2001:bd8:cafe:1::1 1 prefix length value can be omitted. In that case, a value of 128 will be used. """ addr, plen = (addr.split("/") + ["128"])[:2] addr = in6_ptop(addr) plen = int(plen) naddr = inet_pton(socket.AF_INET6, addr) nmask = in6_cidr2mask(plen) prefix = inet_ntop(socket.AF_INET6, in6_and(nmask, naddr)) self.invalidate_cache() self.routes.append((prefix, plen, '::', iff, [addr], 1))