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 diffplot(self, f, delay=1, lfilter=None, **kargs): # type: (Callable, int, Optional[Callable], Any) -> Line2D """diffplot(f, delay=1, lfilter=None) Applies a function to couples (l[i],l[i+delay]) A list of matplotlib.lines.Line2D is returned. """ # Get the list of packets if lfilter is None: lst_pkts = [ f(self.res[i], self.res[i + 1]) for i in range(len(self.res) - delay) ] else: lst_pkts = [ f(self.res[i], self.res[i + 1]) for i in range(len(self.res) - delay) if lfilter(self.res[i]) ] # Mimic the default gnuplot output if kargs == {}: kargs = MATPLOTLIB_DEFAULT_PLOT_KARGS lines = plt.plot(lst_pkts, **kargs) # Call show() if matplotlib is not inlined if not MATPLOTLIB_INLINED: plt.show() return lines
def rec(n, li): sep = ':' if n and n % 2 == 0 else '' if n == 16: return li return rec( n + 1, [ y + sep + '%.2x' % i # faster than '%s%s%.2x' % (y, sep, i) for i in range(*self.parsed[n]) for y in li ])
def get_alias_address(iface_name, ip_mask, gw_str, metric): """ Get the correct source IP address of an interface alias """ # Detect the architecture if consts.IS_64BITS: offset, name_len = 16, 40 else: offset, name_len = 32, 32 # Retrieve interfaces structures sck = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) names = array.array('B', b'\0' * 4096) ifreq = ioctl(sck.fileno(), SIOCGIFCONF, struct.pack("iL", len(names), names.buffer_info()[0])) # Extract interfaces names out = struct.unpack("iL", ifreq)[0] names = names.tobytes() if six.PY3 else names.tostring() names = [ names[i:i + offset].split(b'\0', 1)[0] for i in range(0, out, name_len) ] # noqa: E501 # Look for the IP address for ifname in names: # Only look for a matching interface name if not ifname.decode("utf8").startswith(iface_name): continue # Retrieve and convert addresses ifreq = ioctl(sck, SIOCGIFADDR, struct.pack("16s16x", ifname)) ifaddr = struct.unpack(">I", ifreq[20:24])[0] ifreq = ioctl(sck, SIOCGIFNETMASK, struct.pack("16s16x", ifname)) msk = struct.unpack(">I", ifreq[20:24])[0] # Get the full interface name ifname = plain_str(ifname) if ':' in ifname: ifname = ifname[:ifname.index(':')] else: continue # Check if the source address is included in the network if (ifaddr & msk) == ip_mask: sck.close() return (ifaddr & msk, msk, gw_str, ifname, utils.ltoa(ifaddr), metric) sck.close() return
def _get_values(value): """Generate a range object from (start, stop[, step]) tuples, or return value. """ if (isinstance(value, tuple) and (2 <= len(value) <= 3) and all(hasattr(i, "__int__") for i in value)): # We use values[1] + 1 as stop value for (x)range to maintain # the behavior of using tuples as field `values` return range(*((int(value[0]), int(value[1]) + 1) + tuple(int(v) for v in value[2:]))) return value
def _parse(self): def parse_digit(value, netmask): netmask = min(8, max(netmask, 0)) value = int(value) return (value & (0xff << netmask), (value | (0xff >> (8 - netmask))) + 1) self.parsed = [ parse_digit(x, y) for x, y in zip( struct.unpack("16B", in6_and(self.net, self.mask)), (x - self.plen for x in range(8, 129, 8)), ) ]
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_cidr2mask(m): """ Return the mask (bitstring) associated with provided length value. For instance if function is called on 48, return value is b'\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) # noqa: E501 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', x) for x in t)
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, [x in _rfc1924map for x in 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 Exception: 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 _inet6_ntop(addr): """Convert an IPv6 address from binary form into text representation, used when socket.inet_pton is not available. """ # IPv6 addresses have 128bits (16 bytes) if len(addr) != 16: raise ValueError("invalid length of packed IP address string") # Decode to hex representation address = ":".join(plain_str(bytes_hex(addr[idx:idx + 2])).lstrip('0') or '0' # noqa: E501 for idx in range(0, 16, 2)) try: # Get the longest set of zero blocks. We need to take a look # at group 1 regarding the length, as 0:0:1:0:0:2:3:4 would # have two matches: 0:0: and :0:0: where the latter is longer, # though the first one should be taken. Group 1 is in both # cases 0:0. match = max(_IP6_ZEROS.finditer(address), key=lambda m: m.end(1) - m.start(1)) return '{}::{}'.format(address[:match.start()], address[match.end():]) except ValueError: return address
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
def __iter__(self): for d in range(*self.parsed[3]): for c in range(*self.parsed[2]): for b in range(*self.parsed[1]): for a in range(*self.parsed[0]): yield "%i.%i.%i.%i" % (a, b, c, d)