1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
# Copyright (c) 2016 Red Hat Inc
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
# General networking tools that may be used by all modules
from __future__ import annotations
import re
from struct import pack
from socket import inet_ntoa
from ansible.module_utils.six.moves import zip
VALID_MASKS = [2**8 - 2**i for i in range(0, 9)]
def is_netmask(val):
parts = str(val).split('.')
if not len(parts) == 4:
return False
for part in parts:
try:
if int(part) not in VALID_MASKS:
raise ValueError
except ValueError:
return False
return True
def is_masklen(val):
try:
return 0 <= int(val) <= 32
except ValueError:
return False
def to_netmask(val):
""" converts a masklen to a netmask """
if not is_masklen(val):
raise ValueError('invalid value for masklen')
bits = 0
for i in range(32 - int(val), 32):
bits |= (1 << i)
return inet_ntoa(pack('>I', bits))
def to_masklen(val):
""" converts a netmask to a masklen """
if not is_netmask(val):
raise ValueError('invalid value for netmask: %s' % val)
bits = list()
for x in val.split('.'):
octet = bin(int(x)).count('1')
bits.append(octet)
return sum(bits)
def to_subnet(addr, mask, dotted_notation=False):
""" converts an addr / mask pair to a subnet in cidr notation """
try:
if not is_masklen(mask):
raise ValueError
cidr = int(mask)
mask = to_netmask(mask)
except ValueError:
cidr = to_masklen(mask)
addr = addr.split('.')
mask = mask.split('.')
network = list()
for s_addr, s_mask in zip(addr, mask):
network.append(str(int(s_addr) & int(s_mask)))
if dotted_notation:
return '%s %s' % ('.'.join(network), to_netmask(cidr))
return '%s/%s' % ('.'.join(network), cidr)
def to_ipv6_subnet(addr):
""" IPv6 addresses are eight groupings. The first four groupings (64 bits) comprise the subnet address. """
# https://tools.ietf.org/rfc/rfc2374.txt
# Split by :: to identify omitted zeros
ipv6_prefix = addr.split('::')[0]
# Get the first four groups, or as many as are found + ::
found_groups = []
for group in ipv6_prefix.split(':'):
found_groups.append(group)
if len(found_groups) == 4:
break
if len(found_groups) < 4:
found_groups.append('::')
# Concatenate network address parts
network_addr = ''
for group in found_groups:
if group != '::':
network_addr += str(group)
network_addr += str(':')
# Ensure network address ends with ::
if not network_addr.endswith('::'):
network_addr += str(':')
return network_addr
def to_ipv6_network(addr):
""" IPv6 addresses are eight groupings. The first three groupings (48 bits) comprise the network address. """
# Split by :: to identify omitted zeros
ipv6_prefix = addr.split('::')[0]
# Get the first three groups, or as many as are found + ::
found_groups = []
for group in ipv6_prefix.split(':'):
found_groups.append(group)
if len(found_groups) == 3:
break
if len(found_groups) < 3:
found_groups.append('::')
# Concatenate network address parts
network_addr = ''
for group in found_groups:
if group != '::':
network_addr += str(group)
network_addr += str(':')
# Ensure network address ends with ::
if not network_addr.endswith('::'):
network_addr += str(':')
return network_addr
def to_bits(val):
""" converts a netmask to bits """
bits = ''
for octet in val.split('.'):
bits += bin(int(octet))[2:].zfill(8)
return bits
def is_mac(mac_address):
"""
Validate MAC address for given string
Args:
mac_address: string to validate as MAC address
Returns: (Boolean) True if string is valid MAC address, otherwise False
"""
mac_addr_regex = re.compile('[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$')
return bool(mac_addr_regex.match(mac_address.lower()))
|