def find_binary(cls, ip_version, interval, length, host, marking=None, local_bind=None): """Find a suitable ping executable, looking first for a compatible `fping`, then falling back to the `ping` binary. Binaries are checked for the required capabilities.""" if ip_version == 6: suffix = "6" else: suffix = "" fping = util.which('fping'+suffix) ping = util.which('ping'+suffix) if fping is not None: proc = subprocess.Popen([fping, '-h'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out,err = proc.communicate() # check for presence of timestamp option if "print timestamp before each output line" in str(out): return "{binary} -D -p {interval:.0f} -c {count:.0f} {marking} {local_bind} {host}".format( binary=fping, interval=interval * 1000, # fping expects interval in milliseconds # since there's no timeout parameter for fping, calculate a total number # of pings to send count=length // interval + 1, marking="-O {0}".format(marking) if marking else "", local_bind="-I {0}".format(local_bind) if local_bind else "", host=host) elif "must run as root?" in str(err): sys.stderr.write("Found fping but it seems to be missing permissions (no SUID?). Not using.\n") if ping is not None: # Ping can't handle hostnames for the -I parameter, so do a lookup first. if local_bind: local_bind=util.lookup_host(local_bind, ip_version)[4][0] # Try parsing the output of 'ping' and complain if no data is # returned from the parser. This should pick up e.g. the ping on OSX # not having a -D option and allow us to supply a better error message. proc = subprocess.Popen([ping, '-D', '-n', '-c', '1', 'localhost'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out,err = proc.communicate() if hasattr(out, 'decode'): out = out.decode(ENCODING) if not cls._parse(out)[0]: raise RuntimeError("Cannot parse output of the system ping binary ({ping}). " "Please install fping v3.5+.".format(ping=ping)) return "{binary} -n -D -i {interval:.2f} -w {length:d} {marking} {local_bind} {host}".format( binary=ping, interval=max(0.2, interval), length=length, marking="-Q {0}".format(marking) if marking else "", local_bind="-I {0}".format(local_bind) if local_bind else "", host=host) raise RuntimeError("No suitable ping tool found.")
def get_egress_info(target, ip_version): route = {} if target: ip = util.lookup_host(target, ip_version)[4][0] output = get_command_output("ip route get %s" % ip) if output is not None: # Linux iproute2 syntax. Example: # $ ip r get 8.8.8.8 # 8.8.8.8 via 10.109.3.254 dev wlan0 src 10.109.0.146 # cache parts = iter(output.split()) for p in parts: if p == 'via': route['nexthop'] = next(parts) elif p == 'dev': route['iface'] = next(parts) elif p == 'src': route['src'] = next(parts) else: output = get_command_output("route -n get %s" % ip) if output is not None: # BSD syntax. Example: # $ route -n get 8.8.8.8 # route to: 8.8.8.8 # destination: default # mask: default # gateway: 10.42.7.225 # interface: em0 # flags: <UP,GATEWAY,DONE,STATIC> # recvpipe sendpipe ssthresh rtt,msec mtu weight expire # 0 0 0 0 1500 1 0 for line in output.splitlines(): if not ":" in line: continue k,v = [i.strip() for i in line.split(":")] if k == "gateway": route['nexthop'] = v if k == "interface": route['iface'] = v if route: route['qdiscs'] = get_qdiscs(route['iface']) route['tc_stats_pre'] = get_tc_stats(route['iface']) route['classes'] = get_classes(route['iface']) route['offloads'] = get_offloads(route['iface']) route['bql'] = get_bql(route['iface']) route['driver'] = get_driver(route['iface']) route['link_params'] = get_link_params(route['iface']) route['target'] = ip if not 'nexthop' in route: route['nexthop'] = None return route or None
def lookup_hosts(self): """If no explicit IP version is set, do a hostname lookup and try to""" version = 4 for h in self.HOSTS: try: hostname = util.lookup_host(h) if hostname[0] == socket.AF_INET6: version = 6 except socket.gaierror as e: raise RuntimeError("Hostname lookup failed for host %s: %s" % (h,e)) if self.IP_VERSION is None: self.IP_VERSION = version
def lookup_hosts(self): """If no explicit IP version is set, do a hostname lookup and try to""" version = 4 for h in self.HOSTS: try: hostname = util.lookup_host(h) if hostname[0] == socket.AF_INET6: version = 6 except socket.gaierror as e: raise RuntimeError("Hostname lookup failed for host %s: %s" % (h, e)) if self.IP_VERSION is None: self.IP_VERSION = version