Priyank Chheda
Priyank Chheda

Reputation: 571

Checking if IP address lies within a given range

I want to check if IP 180.179.77.11 lies between a particular range, say 180.179.0.0 - 180.179.255.255.

I wrote a function which will compare every IP octet with the others.

def match(mask, IP):
    min_ip = mask.split(' - ')[0].split('.')
    max_ip = mask.split(' - ')[1].split('.')
    ip = IP.split('.')
    for i in range(4):
        print ip[i] + " < " + min_ip[i] + " or " + ip[i] + " > " + max_ip[i]
        print ip[i] < min_ip[i] or ip[i] > max_ip[i]
        if ip[i] < min_ip[i] or ip[i] > max_ip[i]:
            return False
    return True


match("180.179.0.0 - 180.179.255.255", "180.179.77.11")

OUTPUT:

180 < 180 or 180 > 180
False
179 < 179 or 179 > 179
False
77 < 0 or 77 > 255  # 77 > 255 is true
True
False

However, it doesn't seem to work properly; It looks like the problem occurred in the 3rd octet while comparing 77 with 255.

I have put some print statements to illustrate the problem area.

Upvotes: 5

Views: 3814

Answers (4)

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160377

You are comparing strings values (which compare lexicographically) and not the int values for every IP, make them into ints with comprehensions:

min_ip = [int(i) for i in mask.split(' - ')[0].split('.')]
max_ip = [int(i) for i in mask.split(' - ')[1].split('.')]
ip = [int(i) for i in IP.split('.')]

It's also best if you don't perform the split twice for every ip in mask; split before hand:

s = mask.split(' - ')
min_ip, max_ip = [[int(i) for i in j.split('.')] for j in s]

Your for loop could arguably be better if you used enumerate with ip:

for ind, val in enumerate(ip):
    if val < min_ip[ind] or val > max_ip[ind]:
        return False

Upvotes: 4

Jaimin Ajmeri
Jaimin Ajmeri

Reputation: 602

Without loop, hope its useful.

def match(mask, IP):
    min_ip = mask.split(' - ')[0].split('.')
    max_ip = mask.split(' - ')[1].split('.')
    range4 = range(int(min_ip[-2]), int(max_ip[-2]) + 1)
    range3 = range(int(min_ip[-1]), int(max_ip[-1]) + 1)

    ip = IP.split(".")
    if ( (int(ip[-2]) in range3) and (int(ip[-1]) in range4) ):
        return True

    return False

print match("180.179.0.0 - 180.179.255.255", "180.179.77.11")

Upvotes: 0

Harsha Biyani
Harsha Biyani

Reputation: 7268

What is wrong in your script is - You are comparing string & not numbers.

You can try this:

def match(mask, IP):
    min_ip = mask.split(' - ')[0].split('.')
    print min_ip
    max_ip = mask.split(' - ')[1].split('.')
    print max_ip
    ip = IP.split('.')
    print ip
    for i in range(4):
        if int(ip[i]) < int(min_ip[i]) or int(ip[i]) > int(max_ip[i]):
            return False
    return True
print(match("180.179.0.0 - 180.179.255.255", "180.179.77.11"))

Upvotes: 0

John F
John F

Reputation: 186

When you call the match function strings are passed in which are split according to the octets. However, when the comparisons are made the octet being compared is still a string. Thus '7' > '2' for the third octet. If you convert each octet to an integer as:

if int(ip[i]) < int(min_ip[i]) or int(ip[i]) > int(max_ip[i]):

You will get the expected response.

Upvotes: 3

Related Questions