4

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.

smci
  • 32,567
  • 20
  • 113
  • 146
Priyank Chheda
  • 521
  • 5
  • 16
  • Instead of the `for` loop in your function, you could `return all([ip[i] >= min_ip[i] and ip[i] <= max_ip[i] for i in range(4)])`. Basically it will evaluate the equality expressions and if they are all `True`, it will return `True`. If one or more are `False`, it will return `False`. – jkr Jan 13 '17 at 05:47
  • Thanks...This is neat... – Priyank Chheda Jan 13 '17 at 05:52

4 Answers4

3

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
Enkum
  • 635
  • 8
  • 22
Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
2

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.

John F
  • 176
  • 4
0

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"))
Harsha Biyani
  • 7,049
  • 9
  • 37
  • 61
0

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")
Jaimin Ajmeri
  • 572
  • 3
  • 18