1## This file is part of Scapy 2## See http://www.secdev.org/projects/scapy for more informations 3## Copyright (C) Philippe Biondi <[email protected]> 4## This program is published under a GPLv2 license 5 6""" 7Convert IPv6 addresses between textual representation and binary. 8 9These functions are missing when python is compiled 10without IPv6 support, on Windows for instance. 11""" 12 13from __future__ import absolute_import 14import socket 15import re 16import binascii 17from scapy.modules.six.moves import range 18from scapy.compat import * 19 20_IP6_ZEROS = re.compile('(?::|^)(0(?::0)+)(?::|$)') 21_INET6_PTON_EXC = socket.error("illegal IP address string passed to inet_pton") 22 23def _inet6_pton(addr): 24 """Convert an IPv6 address from text representation into binary form, 25used when socket.inet_pton is not available. 26 27 """ 28 joker_pos = None 29 result = b"" 30 addr = plain_str(addr) 31 if addr == '::': 32 return b'\x00' * 16 33 if addr.startswith('::'): 34 addr = addr[1:] 35 if addr.endswith('::'): 36 addr = addr[:-1] 37 parts = addr.split(":") 38 nparts = len(parts) 39 for i, part in enumerate(parts): 40 if not part: 41 # "::" indicates one or more groups of 2 null bytes 42 if joker_pos is None: 43 joker_pos = len(result) 44 else: 45 # Wildcard is only allowed once 46 raise _INET6_PTON_EXC 47 elif i + 1 == nparts and '.' in part: 48 # The last part of an IPv6 address can be an IPv4 address 49 if part.count('.') != 3: 50 # we have to do this since socket.inet_aton('1.2') == 51 # b'\x01\x00\x00\x02' 52 raise _INET6_PTON_EXC 53 try: 54 result += socket.inet_aton(part) 55 except socket.error: 56 raise _INET6_PTON_EXC 57 else: 58 # Each part must be 16bit. Add missing zeroes before decoding. 59 try: 60 result += hex_bytes(part.rjust(4, "0")) 61 except (binascii.Error, TypeError): 62 raise _INET6_PTON_EXC 63 # If there's a wildcard, fill up with zeros to reach 128bit (16 bytes) 64 if joker_pos is not None: 65 if len(result) == 16: 66 raise _INET6_PTON_EXC 67 result = (result[:joker_pos] + b"\x00" * (16 - len(result)) 68 + result[joker_pos:]) 69 if len(result) != 16: 70 raise _INET6_PTON_EXC 71 return result 72 73 74_INET_PTON = { 75 socket.AF_INET: socket.inet_aton, 76 socket.AF_INET6: _inet6_pton, 77} 78 79 80def inet_pton(af, addr): 81 """Convert an IP address from text representation into binary form.""" 82 # Will replace Net/Net6 objects 83 addr = plain_str(addr) 84 # Use inet_pton if available 85 try: 86 return socket.inet_pton(af, addr) 87 except AttributeError: 88 try: 89 return _INET_PTON[af](addr) 90 except KeyError: 91 raise socket.error("Address family not supported by protocol") 92 93 94def _inet6_ntop(addr): 95 """Convert an IPv6 address from binary form into text representation, 96used when socket.inet_pton is not available. 97 98 """ 99 # IPv6 addresses have 128bits (16 bytes) 100 if len(addr) != 16: 101 raise ValueError("invalid length of packed IP address string") 102 103 # Decode to hex representation 104 address = ":".join(bytes_hex(addr[idx:idx + 2]).decode().lstrip('0') or '0' 105 for idx in range(0, 16, 2)) 106 107 try: 108 # Get the longest set of zero blocks. We need to take a look 109 # at group 1 regarding the length, as 0:0:1:0:0:2:3:4 would 110 # have two matches: 0:0: and :0:0: where the latter is longer, 111 # though the first one should be taken. Group 1 is in both 112 # cases 0:0. 113 match = max(_IP6_ZEROS.finditer(address), 114 key=lambda m: m.end(1) - m.start(1)) 115 return '{}::{}'.format(address[:match.start()], address[match.end():]) 116 except ValueError: 117 return address 118 119 120_INET_NTOP = { 121 socket.AF_INET: socket.inet_ntoa, 122 socket.AF_INET6: _inet6_ntop, 123} 124 125 126def inet_ntop(af, addr): 127 """Convert an IP address from binary form into text representation.""" 128 # Use inet_ntop if available 129 addr = raw(addr) 130 try: 131 return socket.inet_ntop(af, addr) 132 except AttributeError: 133 try: 134 return _INET_NTOP[af](addr) 135 except KeyError: 136 raise ValueError("unknown address family %d" % af) 137