Source code for netdiscover.netdiscover
import os
import subprocess
import sys
import shlex
import re
[docs]class Discover:
def __init__(self, netdiscover_path=None, root_verify=True):
"""
:param netdiscover_path: Path where is the netdiscover binary. If not defined it will search on defaults netdiscover locations
:param root_verify: Verify if the user is root
"""
if root_verify and os.getenv('USER') != 'root':
raise Exception('Programming not running as root.')
path_found = False
netdiscover_search_path = ['netdiscover',
'/usr/bin/netdiscover',
'/usr/sbin/netdiscover',
'/usr/local/bin/netdiscover',
'/sw/bin/netdiscover',
'/opt/local/bin/netdiscover']
if netdiscover_path:
netdiscover_search_path[0] = netdiscover_path
for netdiscover_path in netdiscover_search_path:
try:
if sys.platform.startswith('freebsd') \
or sys.platform.startswith('linux') \
or sys.platform.startswith('darwin'):
p = subprocess.Popen([netdiscover_path, '-help'],
bufsize=10000,
stdout=subprocess.PIPE,
close_fds=True)
else:
p = subprocess.Popen([netdiscover_path, '-help'],
bufsize=10000,
stdout=subprocess.PIPE)
except OSError:
pass
else:
self._netdiscover_path = netdiscover_path # save path
path_found = True
break
if not path_found:
raise Exception("netdiscover not found")
self.command = 'netdiscover -P -N'
[docs] def get_command(self):
"""
:return: Commad used to scan the network
"""
return self.command
[docs] def scan(self, interface=None, ip_range=None, file=None, passive=False, filter_p=None, sleep=None, node=None,
count=None, fast=None, sleep_supression=None, output=["ip","mac"]):
"""
:param interface: Your network device
:param ip_range: Scan a given range instead of auto scan. 192.168.6.0/24,/16,/8
:param file: Scan the list of ranges contained into the given file
:param passive: Do not send anything, only sniff
:param macs: File with the list of known MACs and host names
:param filter_p: Customize pcap filter expression (default: "arp")
:param sleep: Time to sleep between each arp request (miliseconds)
:param node: Last ip octet used for scanning (from 2 to 253)
:param count: Number of times to send each arp reques (for nets with packet loss)
:param fast: Enable fastmode scan, saves a lot of time, recommended for auto
:param sleep_supression: Enable sleep time supression betwen each request (hardcore mode)
:param output: List of elements that should be part of the output, by default thats ip and mac.
:return: List with the result of the scan
"""
self.command = 'netdiscover -P -N'
if interface:
self.command += " -i %s" % interface
if ip_range:
self.command += ' -r %s' % ip_range
if file:
self.command += ' -m %s' % file
if passive:
self.command += ' -p'
"""if macs:
self.command += z"""
if filter_p:
self.command += ' -F %s' % filter_p
if sleep:
self.command += ' -s %d' % sleep
if node:
self.command += ' -n %d' % node
if count:
self.command += ' -c %d' % count
if fast:
self.command += ' -f'
if sleep_supression:
self.command += ' -S'
self._raw_result = subprocess.check_output(shlex.split(self.command))
self._scan_result = self.parse_output(self._raw_result, output)
return self._scan_result
[docs] @staticmethod
def parse_output(data, output):
"""
:param data: Raw output to parse
:param output: List of elements that should be part of the output.
:return: List with the results from the scan. Each result is represented by a dictionary.
"""
# decode and split raw output
content = data.decode("UTF-8").split("\n")
# sanitize user coices for output
output = [key for key in output if key in ("ip","mac","count","len","vendor")]
results = []
if len(content) != 0:
for chunk in content:
pars = re.search(r"\s?(?P<ip>\d+\.\d+\.\d+\.\d+)"
r"\s+(?P<mac>[a-fA-F0-9:]{17})"
r"\s+(?P<count>\d+)"
r"\s+(?P<len>\d+)"
r"\s+(?P<vendor>.*)",
chunk)
if pars:
pars = pars.groupdict()
results.append({key: pars[key] for key in output})
return results