mirror of
https://github.com/lloeki/pingscan.git
synced 2025-12-06 02:54:39 +01:00
initial commit
This commit is contained in:
commit
837d5e349a
1 changed files with 177 additions and 0 deletions
177
pingscan.py
Normal file
177
pingscan.py
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import time
|
||||
import random
|
||||
import threading
|
||||
from threading import Thread
|
||||
|
||||
|
||||
## token management
|
||||
|
||||
_bucket = None
|
||||
|
||||
class Bucket:
|
||||
def __init__(self, token_count):
|
||||
self.tokens = 50
|
||||
|
||||
def take(self):
|
||||
while self.tokens < 0:
|
||||
time.sleep(1)
|
||||
self.tokens = self.tokens - 1
|
||||
|
||||
def give(self):
|
||||
self.tokens = self.tokens + 1
|
||||
|
||||
@staticmethod
|
||||
def get_bucket():
|
||||
global _bucket
|
||||
if _bucket == None:
|
||||
_bucket = Bucket(30)
|
||||
return _bucket
|
||||
|
||||
## safe-ify files WRT threads
|
||||
|
||||
tls = threading.local()
|
||||
|
||||
class ThreadSafeFile(object):
|
||||
def __init__(self, f):
|
||||
self.f = f
|
||||
self.lock = threading.RLock()
|
||||
self.nesting = 0
|
||||
|
||||
def _getlock(self):
|
||||
self.lock.acquire()
|
||||
self.nesting += 1
|
||||
|
||||
def _droplock(self):
|
||||
nesting = self.nesting
|
||||
self.nesting = 0
|
||||
for i in range(nesting):
|
||||
self.lock.release()
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name == 'softspace':
|
||||
return tls.softspace
|
||||
else:
|
||||
raise AttributeError(name)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name == 'softspace':
|
||||
tls.softspace = value
|
||||
else:
|
||||
return object.__setattr__(self, name, value)
|
||||
|
||||
def write(self, data):
|
||||
self._getlock()
|
||||
self.f.write(data)
|
||||
if data == '\n':
|
||||
self._droplock()
|
||||
|
||||
## functional threading
|
||||
|
||||
class FunctionThread(Thread):
|
||||
def __init__(self, function, *args, **kwargs):
|
||||
Thread.__init__(self)
|
||||
self.function = function
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
|
||||
def run(self):
|
||||
self.function(*self.args, **self.kwargs)
|
||||
|
||||
def test(message):
|
||||
time.sleep(random.random())
|
||||
print message
|
||||
|
||||
## pinger
|
||||
|
||||
def ping(ip, on_start, on_completion):
|
||||
on_start(ip)
|
||||
lifeline = re.compile(r"(\d) packets received")
|
||||
pingaling = os.popen("ping -q -W1 -c2 %s 2> /dev/null" % ip,"r")
|
||||
while True:
|
||||
line = pingaling.readline()
|
||||
if not line:
|
||||
break
|
||||
igot = re.findall(lifeline, line)
|
||||
if igot:
|
||||
on_completion(ip, int(igot[0]))
|
||||
|
||||
## ip tools
|
||||
|
||||
def ipv4_to_int(string):
|
||||
ipv4 = re.compile(r"(\d+).(\d+).(\d+).(\d+)")
|
||||
values = re.findall(ipv4, string)[0]
|
||||
address = (int(values[0])*256**3 +
|
||||
int(values[1])*256**2 +
|
||||
int(values[2])*256 +
|
||||
int(values[3]))
|
||||
return address
|
||||
|
||||
def int_to_ipv4(address):
|
||||
blocks = [ ]
|
||||
blocks.append(address & 0x000000FF)
|
||||
blocks.append((address & 0x0000FF00) / 256)
|
||||
blocks.append((address & 0x00FF0000) / 256**2)
|
||||
blocks.append((address & 0xFF000000) / 256**3)
|
||||
return "%d.%d.%d.%d" % (blocks[3], blocks[2], blocks[1], blocks[0])
|
||||
|
||||
def cidr_mask(bits):
|
||||
mask_bits = [ 1 for i in range(32-bits, 32)] + [ 0 for i in range(0, 32-bits) ]
|
||||
mask = sum([mask_bits[i]*2**(31-i) for i in range(0,32)])
|
||||
return mask
|
||||
|
||||
def cidr_range(address, bits, width=32):
|
||||
mask = cidr_mask(bits)
|
||||
start = mask & address
|
||||
end = start | ~mask & 2**width-1
|
||||
return (start, end)
|
||||
|
||||
def ipv4_xrange(cidr_net):
|
||||
cidr = re.compile(r"([^/]+)/(\d+)")
|
||||
cidr_values = re.findall(cidr, cidr_net)[0]
|
||||
address = ipv4_to_int(cidr_values[0])
|
||||
slash = int(cidr_values[1])
|
||||
(start, end) = cidr_range(address, slash)
|
||||
for address in xrange(start+1, end-1):
|
||||
yield address
|
||||
raise StopIteration
|
||||
|
||||
## threaded range pinger
|
||||
|
||||
def start_ping(ip):
|
||||
#print "%s: pinging..." % ip
|
||||
Bucket.get_bucket().take()
|
||||
|
||||
def give_result(ip, replies):
|
||||
Bucket.get_bucket().give()
|
||||
if replies > 0:
|
||||
result = "alive (%s)" % replies
|
||||
else:
|
||||
result = "no reply"
|
||||
return
|
||||
print "%s: %s" % (ip, result)
|
||||
|
||||
def ping_range(cidr):
|
||||
pingers = []
|
||||
for ip in ipv4_xrange(cidr):
|
||||
pinger = FunctionThread(ping, int_to_ipv4(ip), start_ping, give_result)
|
||||
pinger.start()
|
||||
pingers.append(pinger)
|
||||
time.sleep(0.1)
|
||||
|
||||
for pinger in pingers:
|
||||
pinger.join()
|
||||
|
||||
## main
|
||||
|
||||
if __name__ == "__main__":
|
||||
# sanitize stdout
|
||||
sys.stdout = ThreadSafeFile(sys.stdout)
|
||||
|
||||
print "Starting pinging %s..." % sys.argv[1]
|
||||
ping_range(sys.argv[1])
|
||||
print "Done!"
|
||||
Loading…
Add table
Add a link
Reference in a new issue