blob: 4e2778d6fa08accb30587c52b15945bfdffb9a3f [file] [log] [blame]
import json
import os
import platform
import sys
from copy import deepcopy
from multiprocessing.dummy import Pool
from subprocess import PIPE, Popen
_os = platform.system()
_packets = {}
_defaults = {
"ip": None,
"size": 0,
"fragmentation": False,
"count": 1,
"exit_timeout": 1,
"response_timeout": 1,
"numeric": True
}
_help_message = \
"Invalid parameters. Use: 'ping.py [PKT_SIZE] <IP>' or 'ping.py n.json'\n"
_template = {
"returncode": -1,
"stdout": "",
"stderr": ""
}
def shell(command):
_ps = Popen(
" ".join(command),
shell=True,
stdout=PIPE,
stderr=PIPE
)
_out = _ps.communicate()
_err = _out[1]
_out = _out[0]
return _ps.returncode, _out, _err
def write_help():
_t = deepcopy(_template)
_t["returncode"] = 1
_t["stderr"] = _help_message
write_outcome(_t)
def write_outcome(_params):
sys.stdout.write(json.dumps(_params))
def do_ping(_params):
# Load params and defaults
_d = deepcopy(_defaults)
for key in _params:
_d[key] = _params[key]
# Build cmd
_cmd = ["ping"]
if _os == "Darwin":
if not _d["fragmentation"]:
_cmd.append("-D")
if _d["exit_timeout"]:
_cmd += ["-t", str(_d["exit_timeout"])]
elif _os == "Linux":
if not _d["fragmentation"]:
_cmd += ["-M", "do"]
if _d["exit_timeout"]:
_cmd += ["-w", str(_d["exit_timeout"])]
else:
# Windows or other OS
_t = deepcopy(_template)
_t["returncode"] = 1
_t["stderr"] = \
"ping.py: '{}' support not implemented".format(_os)
write_outcome(_t)
sys.exit(1)
if _d["size"]:
_cmd += ["-s", str(_d["size"])]
if _d["count"]:
_cmd += ["-c", str(_d["count"])]
if _d["numeric"]:
_cmd.append("-n")
if _d["response_timeout"]:
_cmd += ["-W", str(_d["response_timeout"])]
_cmd.append(_d["ip"])
# sys.stdout.write("# {}\n".format(" ".join(_cmd)))
_r, _out, _err = shell(_cmd)
# TODO: parse results, latency, etc
_t = deepcopy(_template)
_t["returncode"] = _r
_t["stdout"] = _out
_t["stderr"] = _err
_params.update(_t)
return _params
def load_targets(filename):
# load target ips from json
with open(filename, "r") as f:
j = json.load(f)
return j
if len(sys.argv) < 2:
# no params given
write_help()
elif len(sys.argv) < 3:
# one param: decide if it json file or IP
_arg = sys.argv[1]
if os.path.isfile(_arg):
_packets = load_targets(_arg)
# up to 15 packets at once
pool = Pool(15)
# prepare threaded map
_param_map = []
for _node, _data in _packets.iteritems():
if isinstance(_data, list):
for target in _data:
_param_map.append(target)
elif isinstance(_data, dict):
_param_map.append(_data)
else:
_t = deepcopy(_template)
_t["returncode"] = 1
_t["stderr"] = \
"TypeError: 'list' or 'dict' expected. " \
"Got '{}': '{}'".format(
type(_data).__name__,
_data
)
_packets[_node] = _t
_threaded_out = pool.map(do_ping, _param_map)
for _out in _threaded_out:
if isinstance(_packets[_out["tgt_host"]], dict):
_packets[_out["tgt_host"]] = _out
elif isinstance(_packets[_out["tgt_host"]], list):
_packets[_out["tgt_host"]][_out["ip_index"]] = _out
sys.stdout.write(json.dumps(_packets))
else:
# IP given
_ip = sys.argv[1]
write_outcome(do_ping(_ip))
elif len(sys.argv) < 4:
# two params: size and IP
_s = sys.argv[1]
_ip = sys.argv[2]
write_outcome(do_ping(_ip, size=_s))
else:
# too many params given
write_help()