4.6. Transport IPv4/IPv6
4.6.1. IP
4.6.2. IPv4
socket.AF_INET
4.6.3. IPv6
socket.AF_INET6
4.6.4. ipaddress
In stdlib since Python 3.3
4.6.5. IP Addresses
import ipaddress
ipaddress.ip_address('192.168.0.1')
# IPv4Address('192.168.0.1')
ipaddress.ip_address('2001:db8::')
# IPv6Address('2001:db8::')
import ipaddress
ipaddress.IPv4Address('192.168.0.1')
# IPv4Address('192.168.0.1')
ipaddress.IPv4Address(3232235521)
# IPv4Address('192.168.0.1')
ipaddress.IPv4Address(b'\xC0\xA8\x00\x01')
# IPv4Address('192.168.0.1')
Comparison:
IPv4Address('127.0.0.2') > IPv4Address('127.0.0.1')
# True
IPv4Address('127.0.0.2') == IPv4Address('127.0.0.1')
# False
IPv4Address('127.0.0.2') != IPv4Address('127.0.0.1')
# True
IPv4Address('127.0.0.2') + 3
# IPv4Address('127.0.0.5')
IPv4Address('127.0.0.2') - 3
# IPv4Address('126.255.255.255')
IPv4Address('255.255.255.255') + 1
# Traceback (most recent call last):
# ipaddress.AddressValueError: 4294967296 (>= 2**32) is not permitted as an IPv4 address
The name of the reverse DNS PTR record for the IP address:
ipaddress.ip_address("127.0.0.1").reverse_pointer
# '1.0.0.127.in-addr.arpa'
ipaddress.ip_address("2001:db8::1").reverse_pointer
# '1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa'
4.6.6. IP Network
import ipaddress
ipaddress.ip_network('192.168.0.0/28')
# IPv4Network('192.168.0.0/28')
list(ip_network('192.0.2.0/29').hosts()) #doctest: +NORMALIZE_WHITESPACE
# [IPv4Address('192.0.2.1'), IPv4Address('192.0.2.2'),
# IPv4Address('192.0.2.3'), IPv4Address('192.0.2.4'),
# IPv4Address('192.0.2.5'), IPv4Address('192.0.2.6')]
list(ip_network('192.0.2.0/31').hosts())
# [IPv4Address('192.0.2.0'), IPv4Address('192.0.2.1')]
n1 = ip_network('192.0.2.0/28')
n2 = ip_network('192.0.2.1/32')
list(n1.address_exclude(n2))
# [IPv4Network('192.0.2.8/29'), IPv4Network('192.0.2.4/30'),
# IPv4Network('192.0.2.2/31'), IPv4Network('192.0.2.0/32')]
Subnet:
list(ip_network('192.0.2.0/24').subnets())
# [IPv4Network('192.0.2.0/25'), IPv4Network('192.0.2.128/25')]
list(ip_network('192.0.2.0/24').subnets(prefixlen_diff=2))
# [
# IPv4Network('192.0.2.0/26'),
# IPv4Network('192.0.2.64/26'),
# IPv4Network('192.0.2.128/26'),
# IPv4Network('192.0.2.192/26')
# ]
list(ip_network('192.0.2.0/24').subnets(new_prefix=26))
# [
# IPv4Network('192.0.2.0/26'),
# IPv4Network('192.0.2.64/26'),
# IPv4Network('192.0.2.128/26'),
# IPv4Network('192.0.2.192/26')
# ]
list(ip_network('192.0.2.0/24').subnets(new_prefix=23))
# Traceback (most recent call last):
# ValueError: new prefix must be longer
list(ip_network('192.0.2.0/24').subnets(new_prefix=25))
# [
# IPv4Network('192.0.2.0/25'),
# IPv4Network('192.0.2.128/25')
# ]
Supernet:
ip_network('192.0.2.0/24').supernet()
# IPv4Network('192.0.2.0/23')
ip_network('192.0.2.0/24').supernet(prefixlen_diff=2)
# IPv4Network('192.0.0.0/22')
ip_network('192.0.2.0/24').supernet(new_prefix=20)
# IPv4Network('192.0.0.0/20')
Comparison:
a = ip_network('192.168.1.0/24')
b = ip_network('192.168.1.128/30')
b.subnet_of(a)
# True
ip_network('192.0.2.1/32').compare_networks(ip_network('192.0.2.2/32'))
# -1
ip_network('192.0.2.1/32').compare_networks(ip_network('192.0.2.0/32'))
# 1
ip_network('192.0.2.1/32').compare_networks(ip_network('192.0.2.1/32'))
# 0
Iteration:
for addr in IPv4Network('192.0.2.0/28'):
addr
# IPv4Address('192.0.2.0')
# IPv4Address('192.0.2.1')
# IPv4Address('192.0.2.2')
# IPv4Address('192.0.2.3')
# IPv4Address('192.0.2.4')
# IPv4Address('192.0.2.5')
# IPv4Address('192.0.2.6')
# IPv4Address('192.0.2.7')
# IPv4Address('192.0.2.8')
# IPv4Address('192.0.2.9')
# IPv4Address('192.0.2.10')
# IPv4Address('192.0.2.11')
# IPv4Address('192.0.2.12')
# IPv4Address('192.0.2.13')
# IPv4Address('192.0.2.14')
# IPv4Address('192.0.2.15')
IPv4Network('192.0.2.0/28')[0]
# IPv4Address('192.0.2.0')
IPv4Network('192.0.2.0/28')[15]
# IPv4Address('192.0.2.15')
IPv4Address('192.0.2.6') in IPv4Network('192.0.2.0/28')
# True
IPv4Address('192.0.3.6') in IPv4Network('192.0.2.0/28')
# False
4.6.7. Interface
ipaddress.IPv4Interface
ipaddress.IPv6Interface
interface = IPv4Interface('192.0.2.5/24')
interface.ip
# IPv4Address('192.0.2.5')
interface = IPv4Interface('192.0.2.5/24')
interface.network
# IPv4Network('192.0.2.0/24')
interface = IPv4Interface('192.0.2.5/24')
interface.with_prefixlen
# '192.0.2.5/24'
interface = IPv4Interface('192.0.2.5/24')
interface.with_netmask
# '192.0.2.5/255.255.255.0'
interface = IPv4Interface('192.0.2.5/24')
interface.with_hostmask
# '192.0.2.5/0.0.0.255'
4.6.8. netaddr
4.6.9. Installation
$ pip install netaddr
4.6.10. Layer 3 addressing (IP)
from netaddr import IPAddress
ip = IPAddress('192.21.8.11')
ip.version
# 4
dir(ip)
# [ ... Snipped... 'bin', 'bits', 'format', 'info', 'ipv4', 'ipv6',
# 'is_hostmask', 'is_ipv4_compat', 'is_ipv4_mapped', 'is_link_local',
# 'is_loopback', 'is_multicast', 'is_netmask', 'is_private', 'is_reserved',
# 'is_unicast', 'key', 'netmask_bits', 'packed', 'reverse_dns', 'sort_key',
# 'value', 'version', 'words']
ip.bin
# '0b11000000000101010000100000001011'
ip.bits()
# '11000000.00010101.00001000.00001011'
ip.words
# (192, 21, 8, 11)
ip.packed
# '\xc0\x15\x08\x0b'
ip.version
# 6
ip.is_unicast()
# True
ip.is_link_local()
# True
4.6.11. IPNetwork
from netaddr import IPNetwork
ip_range = IPNetwork('192.241.21.6/24')
dir(ip_range)
# [ ... snipped ... 'broadcast', 'cidr', 'first', 'hostmask', 'info',
# 'ip', 'ipv4', 'ipv6', 'is_ipv4_compat', 'is_ipv4_mapped', 'is_link_local',
# 'is_loopback', 'is_multicast', 'is_private', 'is_reserved', 'is_unicast',
# 'iter_hosts', 'key', 'last', 'netmask', 'network', 'next', 'prefixlen',
# 'previous', 'size', 'sort_key', 'subnet', 'supernet', 'value', 'version']
ip_range.network
# IPAddress('192.241.21.0')
ip_range.hostmask
# IPAddress('0.0.0.255')
ip_range.netmask
# IPAddress('255.255.255.0')
ip_range.broadcast
# IPAddress('192.241.21.255')
ip_range.size
# 256
for i in ip_range:
print(i)
# 192.241.21.0
# 192.241.21.1
# ... snipped ...
# 192.241.21.255
4.6.12. List operations on IPNetwork object
ip_range = IPNetwork('192.0.2.16/29')
ip_range_list = list(ip_range)
len(ip_range_list)
# 8
ip_range_list
# [IPAddress('192.0.2.16'), IPAddress('192.0.2.17'), ...snipped... IPAddress('192.0.2.23')]
ip_range_list[6] # indexing
# IPAddress('192.0.2.22')
ip_range_list[2:5] # slicing
# [IPAddress('192.0.2.18'), IPAddress('192.0.2.19'), IPAddress('192.0.2.20')]
4.6.13. IPRange
ip_range = IPRange('192.168.1.0', '192.168.1.20')
for i in ip_range:
print(i)
# 192.168.1.0
# ... snipped ...
# 192.168.1.19
# 192.168.1.20
4.6.14. IP sets
IPSet(['192.0.2.0'])
# IPSet(['192.0.2.0/32'])
IPSet([IPAddress('192.0.2.0')])
# IPSet(['192.0.2.0/32'])
IPSet([IPNetwork('192.0.2.0/24')])
# IPSet(['192.0.2.0/24'])
IPSet(IPRange("10.0.0.0", "10.0.1.31"))
# IPSet(['10.0.0.0/24', '10.0.1.0/27'])
for ip in IPSet(['192.0.2.0/28']):
print(ip)
# 192.0.2.0
# 192.0.2.1
# ... snipped ...
# 192.168.2.15
4.6.15. Adding and removing set elements
from netaddr import IPSet
s1 = IPSet()
s1.add('192.168.1.0/30')
s1.size
# 4
'192.168.1.3' in s1
# True
s1.remove('192.168.1.3')
s1.size
# 3
scan1 = IPSet(['192.168.1.0/30'])
scan1
# IPSet(['192.168.1.0/30'])
scan1.size
# 4
scan2 = IPSet(['192.168.1.0/31'])
scan2.size
# 2
scan1 | scan2
# IPSet(['192.168.1.0/30'])
scan1 & scan2
# IPSet(['192.168.1.0/31'])
scan1 ^ scan2
# IPSet(['192.168.1.2/31'])
4.6.16. Layer 2 addressing (MAC)
mac = EUI('ec:f4:bb:87:2d:0c')
dir(mac)
# ... snipped ... 'bin', 'bits', 'dialect', 'ei', 'eui64', 'iab',
# 'info', 'ipv6', 'ipv6_link_local', 'is_iab', 'modified_eui64', 'oui',
# 'packed', 'value', 'version', 'words']
str(mac), str(mac.ei), str(mac.oui), str(mac.version)
# ('EC-F4-BB-87-2D-0C', '87-2D-0C', 'EC-F4-BB', '48')
mac.info
# {'OUI': {'address': ['one dell way',
# 'MS:RR5-45',
# 'Round rock Texas 78682',
# 'UNITED STATES'],
# 'idx': 15529147,
# 'offset': 3429092,
# 'org': 'Dell Inc',
# 'oui': 'EC-F4-BB',
# 'size': 141}}
oui = mac.oui
dir(oui)
# [ ... snipped ... 'records', 'reg_count', 'registration']
oui.registration().org
# 'Dell Inc'
oui.registration().address
# ['one dell way', 'MS:RR5-45', 'Round rock Texas 78682', 'UNITED STATES']