Search code examples
pythonip-address

Use python IP address to mask IP addresses


I'm new to IP addresses, so forgive me if I'm using some terminology incorrectly.

I would like to take IP address and get their address with the final octet zeroed out. Similar, bitwise, to multiplying by 255.255.255.0.

With strings alone, this would do the job:

ip_address = '192.168.1.1'
octets = ip_address.split('.')
masked_address = '.'.join(octets[:-1]) + '.0'

However, I would like to be able to draw from different sources while creating the collection. Sometimes I have bytes representations of IP addresses, sometimes integer, sometimes string. Hence, it's easiest if I know how to do this on a collection where the data is stored as python ipaddress.IPAddress (4 and 6...) objects. The workflow would be: take ip addresses from different sources, turn to python IP objects, merge collections, transfrom to IP/24 type addresses. But I don't see anything in the ipaddress docs that makes clear how to do the last step.


Solution

  • Manipulating ip addresses is just bitwise math.

    If you have an address in an ipaddress.IPv4Address object, you can zero out the last octet by writing:

    >>> x = ipaddress.ip_address('192.168.1.1')
    >>> y = ipaddress.ip_address(int(x) & 0xffffff00)
    >>> y
    IPv4Address('192.168.1.0')
    

    Where 0xffffff00 is just the equivalent of 255.255.255.0. You could of course write:

    >>> mask = int(ipaddress.ip_address('255.255.255.0'))
    >>> y = ipaddress.ip_address(int(x) & mask)
    

    Or even:

    >>> mask = (2**(ipaddress.IPV4LENGTH))-256
    >>> y = ipaddress.ip_address(int(x) & mask)
    

    Similarly, with an IPv6Address object:

    >>> x = ipaddress.ip_address('1234::1')
    >>> mask = (2**(ipaddress.IPV6LENGTH))-256
    >>> y = ipaddress.ip_address(int(x) & mask)
    >>> y
    IPv6Address('1234::')
    

    Here, we're setting mask to the "all ones" address (2**129)-1) and then setting the last octet to zero by subtracting 255.