reorx
1/12/2016 - 3:58 PM

cidr_match.py

#!/usr/bin/env python
# coding: utf-8

import socket
import struct


def ip2long(ip):
    """Convert an IP string to long"""
    packedip = socket.inet_aton(ip)
    return struct.unpack("!L", packedip)[0]


def cidr_match(ip, cidr_range):
    subnet, bits = tuple(cidr_range.split('/'))
    bits = int(bits)
    ip = ip2long(ip)
    subnet = ip2long(subnet)
    mask = -1 << (32 - bits)
    subnet &= mask
    return (ip & mask) == subnet


if __name__ == '__main__':
    test_data = [
        ['10.10.0.0', '10.10.0.0/32', True],

        ['10.10.0.1', '10.10.0.0/31', True],
        ['10.10.0.0', '10.10.0.1/31', True],
        ['10.10.0.2', '10.10.0.1/31', False],

        ['10.10.0.0', '10.10.0.0/24', True],
        ['10.10.0.255', '10.10.0.0/24', True],
        ['10.10.1.255', '10.10.0.0/24', False],

        ['10.10.0.0', '10.10.0.1/24', True],
        ['10.10.0.255', '10.10.0.128/24', True],
        ['10.10.1.255', '10.10.0.255/24', False],

        ['192.168.0.0', '192.168.0.0/16', True],
        ['192.168.255.255', '192.168.0.0/16', True],
        ['192.169.0.0', '192.168.0.0/16', False],

        ['192.168.0.0', '192.168.1.1/16', True],
        ['192.168.255.255', '192.168.128.128/16', True],
        ['192.169.0.0', '192.168.255.255/16', False],
    ]

    for i in test_data:
        assert cidr_match(i[0], i[1]) == i[2]