Created
December 24, 2019 05:29
-
-
Save lewisxy/1be90b901492656f3c424443350ad98b to your computer and use it in GitHub Desktop.
select random IP from a specified range
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/python3 | |
import json | |
import random | |
example_data = """ | |
[ | |
{ | |
"type": "range", | |
"name": "myRange", | |
"range_begin": "1.2.3.4", | |
"range_end": "1.2.3.5" | |
}, | |
{ | |
"type": "list", | |
"name": "local gateway", | |
"list_data": [ | |
"192.168.1.1", | |
"192.169.2.2" | |
] | |
}, | |
{ | |
"type": "cidr", | |
"name": "myCidr", | |
"cidr_data": "123.234.0.0/31" | |
} | |
] | |
""" | |
# goal: given a list of ips, in above format, return a random ip | |
# idea: parse json, create a list of IpRange objects | |
# then compute the total number of ips | |
# find a random numnber within this range, | |
# then convert the index into a value of a specific index of an object | |
# call object.find(index) to return | |
def ip_to_int(ip): | |
try: | |
a, b, c, d = ip.split(".") | |
a = int(a) | |
b = int(b) | |
c = int(c) | |
d = int(d) | |
assert(a >= 0 and a <= 255) | |
assert(b >= 0 and b <= 255) | |
assert(c >= 0 and c <= 255) | |
assert(d >= 0 and d <= 255) | |
return ((a & 0xff) << 24) + ((b & 0xff) << 16) + ((c & 0xff) << 8) + (d & 0xff) | |
except: # Exception as e: | |
#print(e) | |
print("{} is not a valid IP".format(ip)) | |
return None | |
def int_to_ip(n): | |
try: | |
a = (n >> 24) & 0xff | |
b = (n >> 16) & 0xff | |
c = (n >> 8) & 0xff | |
d = n & 0xff | |
return ".".join([str(a), str(b), str(c), str(d)]) | |
except: #Exception as e: | |
#print(e) | |
print("{} is not a valid int for IP".format(n)) | |
return None | |
# a = ip_to_int("255.255.255.0") | |
# print(a) | |
# print(int_to_ip(a)) | |
# prototype functions for closure | |
def proto_find_list(lst): | |
l = len(lst) | |
def f(i): | |
if (i >= l or i < 0): | |
print("Out of Bound") | |
return None | |
else: | |
return lst[i] | |
return (l, f) | |
def proto_find_range(begin, end): | |
begin_num = ip_to_int(begin) | |
end_num = ip_to_int(end) | |
l = end_num - begin_num + 1 | |
if (l < 0): | |
print("Invalid Range") | |
return None | |
def f(i): | |
if (i >= l or i < 0): | |
print("Out of Bound") | |
return None | |
else: | |
return int_to_ip(begin_num + i) | |
return (l, f) | |
def proto_find_cidr(cidr): | |
try: | |
ip, bitlen = cidr.split("/") | |
bitlen = int(bitlen) | |
assert(bitlen <= 32 and bitlen >= 0) | |
remainlen = 32 - bitlen | |
l = (1 << remainlen) | |
base = (ip_to_int(ip) >> remainlen) << remainlen | |
except: #Exception as e: | |
#print(e) | |
print("{} is not a valid CIDR") | |
return None | |
def f(i): | |
if (i >= l or i < 0): | |
print("Out of Bound") | |
return None | |
else: | |
return int_to_ip(base + i) | |
return (l, f) | |
class IpRange: | |
def __init__(self, entry): | |
self.name = entry["name"] # str: name of list | |
entry_type = entry["type"] | |
if (entry_type == "range"): | |
self.size, self.find = proto_find_range(entry["range_begin"], entry["range_end"]) | |
elif (entry_type == "list"): | |
self.size, self.find = proto_find_list(entry["list_data"]) | |
elif (entry_type == "cidr"): | |
self.size, self.find = proto_find_cidr(entry["cidr_data"]) | |
else: | |
print("Invalid type: {}".format(entry_type)) | |
def build_list(entrylist): | |
res = [IpRange(x) for x in entrylist] | |
count = 0 | |
for x in res: | |
count += x.size | |
return (count, res) | |
def randIP(lst, size): | |
num = random.randint(0, size - 1) | |
for x in lst: | |
if num < x.size: | |
return x.find(num) | |
else: | |
num -= x.size | |
if __name__ == "__main__": | |
# filename = "filename.json" | |
# with open(filename, "rb") as f: | |
# data = json.loads(f.read()) | |
data = json.loads(example_data) | |
count, res = build_list(data) | |
print("{} IPs loaded".format(count)) | |
for _ in range(10): | |
print(randIP(res, count)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment