From 31b1a4e94e6c90433cf81d79614be7b62b4476ad Mon Sep 17 00:00:00 2001 From: Brad Walker Date: Thu, 19 Mar 2015 20:47:36 -0600 Subject: [PATCH] Use an iterator of octet quadruples instead of building a list of strings. The latter could possibly exhaust memory (0/0) and would pause before ping sweeping other subnets. --- pingrange.py | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/pingrange.py b/pingrange.py index 1d89b3c..d88f29b 100644 --- a/pingrange.py +++ b/pingrange.py @@ -21,34 +21,39 @@ # python pingrange.py 10.1.0-1.0-255 will ping 10.1.0.0/23 # # +import itertools import re try: - from cli import cli + from cli import cli except ImportError: - from cisco import cli + from cisco import cli from argparse import ArgumentParser -def expandrange(rangefunc): - hosts = [] - octets = rangefunc.split('.') - for i,octet in enumerate(octets): - if '-' in octet: - octetrange = octet.split('-') - for digit in range(int(octetrange[0]), int(octetrange[1])+1): - ip = '.'.join(octets[:i] + [str(digit)] + octets[i+1:]) - hosts += expandrange(ip) - break - else: - hosts.append(rangefunc) - return hosts + +def parse_octet_ranges(octet_ranges_spec): + """ + Parses IP range spec into four iterables of numbers corresponding to each + octet's range. + """ + octet_ranges = [ + [int(n) for n in octet_range.split('-')] + for octet_range in octet_ranges_spec.split('.') + ] + return [ + octet_range if len(octet_range) == 1 + else range(octet_range[0], octet_range[1] + 1) + for octet_range in octet_ranges + ] + parser = ArgumentParser('pingrange') parser.add_argument('ip', help='IP range to ping, e.g., 10.1.0-1.0-255 will expand to 10.1.0.0/23') parser.add_argument('options', nargs='*', help='Options to pass to ping', default=['count 1']) args = parser.parse_args() -targets = expandrange(args.ip) +a_range, b_range, c_range, d_range = parse_octet_ranges(args.ip) -for ip in targets: +for a, b, c, d in itertools.product(a_range, b_range, c_range, d_range): + ip = '%d.%d.%d.%d' % (a, b, c, d) m = re.search('([0-9\.]+)% packet loss', cli('ping %s %s' % (ip, ' '.join(args.options)))) print('%s - %s' % (ip, 'UP' if float(m.group(1)) == 0.0 else 'DOWN'))