def test_osx_parse(self): """ Test parsing ping output on OSX. """ output = """ PING 127.0.0.1 (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.052 ms 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.136 ms 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.080 ms --- 127.0.0.1 ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 0.052/0.089/0.136/0.035 ms """ parsed = pingparser.parse(output) self.assertEqual(parsed['host'], '127.0.0.1') self.assertEqual(parsed['sent'], '3') self.assertEqual(parsed['received'], '3') self.assertEqual(parsed['packet_loss'], '0.0') self.assertEqual(parsed['min_ping'], '0.052') self.assertEqual(parsed['avg_ping'], '0.089') self.assertEqual(parsed['max_ping'], '0.136') self.assertEqual(parsed['jitter'], '0.035')
def test_windows_parse_host_unreachable(self): """ Test parsing a ping on Windows that returns host not reachable. """ output = """ Pinging 10.0.1.15 with 32 bytes of data: Reply from 10.0.1.14: Destination host unreachable. Reply from 10.0.1.14: Destination host unreachable. Reply from 10.0.1.14: Destination host unreachable. Reply from 10.0.1.14: Destination host unreachable. Ping statistics for 10.0.1.15: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), """ parsed = pingparser.parse(output) self.assertEqual(parsed['host'], '10.0.1.15') self.assertEqual(parsed['sent'], '4') # The following two fields accurately represent what Windows ping returns but I don't # think they really make sense. This ought to 100% loss and 0 packets received. # In other words, this test is valid but Windows ping is not in my opinion. self.assertEqual(parsed['received'], '4') self.assertEqual(parsed['packet_loss'], '0') self.assertEqual(parsed['min_ping'], 'NA') self.assertEqual(parsed['avg_ping'], 'NA') self.assertEqual(parsed['max_ping'], 'NA')
def test_windows_parse_host_half_unreachable(self): """ Test parsing a ping on Windows that returns host not reachable but only for some events. """ output = """ Pinging 10.0.1.15 with 32 bytes of data: Request timed out. Request timed out. Reply from 10.0.1.14: Destination host unreachable. Reply from 10.0.1.14: Destination host unreachable. Ping statistics for 10.0.1.15: Packets: Sent = 4, Received = 2, Lost = 2 (50% loss), """ parsed = pingparser.parse(output) self.assertEqual(parsed['host'], '10.0.1.15') self.assertEqual(parsed['sent'], '4') self.assertEqual(parsed['received'], '2') self.assertEqual(parsed['packet_loss'], '50') self.assertEqual(parsed['min_ping'], 'NA') self.assertEqual(parsed['avg_ping'], 'NA') self.assertEqual(parsed['max_ping'], 'NA')
def test_windows_parse_domain(self): """ Test parsing a ping on Windows to a domain name. """ output = """ Pinging google.com [74.125.202.100] with 32 bytes of data: Reply from 74.125.202.100: bytes=32 time=45ms TTL=44 Reply from 74.125.202.100: bytes=32 time=45ms TTL=44 Reply from 74.125.202.100: bytes=32 time=45ms TTL=44 Reply from 74.125.202.100: bytes=32 time=45ms TTL=44 Ping statistics for 74.125.202.100: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 45ms, Maximum = 45ms, Average = 45ms """ parsed = pingparser.parse(output) self.assertEqual(parsed['host'], 'google.com') self.assertEqual(parsed['sent'], '4') self.assertEqual(parsed['received'], '4') self.assertEqual(parsed['packet_loss'], '0') self.assertEqual(parsed['min_ping'], '45') self.assertEqual(parsed['avg_ping'], '45') self.assertEqual(parsed['max_ping'], '45') self.assertEqual(parsed['jitter'], None) # Windows ping currently doesn't include jitter
def test_windows_parse_localhost(self): """ Test parsing a ping on Windows by IP (to localhost). """ output = """Pinging 127.0.0.1 with 32 bytes of data: Reply from 127.0.0.1: bytes=32 time<1ms TTL=128 Reply from 127.0.0.1: bytes=32 time<1ms TTL=128 Reply from 127.0.0.1: bytes=32 time<1ms TTL=128 Ping statistics for 127.0.0.1: Packets: Sent = 3, Received = 3, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 0ms, Maximum = 0ms, Average = 0ms """ parsed = pingparser.parse(output) self.assertEqual(parsed['host'], '127.0.0.1') self.assertEqual(parsed['sent'], '3') self.assertEqual(parsed['received'], '3') self.assertEqual(parsed['packet_loss'], '0') self.assertEqual(parsed['min_ping'], '0') self.assertEqual(parsed['avg_ping'], '0') self.assertEqual(parsed['max_ping'], '0') self.assertEqual(parsed['jitter'], None) # Windows ping currently doesn't include jitter
def ping(host, count=1, index=None, sourcetype="ping", source="ping_search_command", logger=None): """ Pings the host using the native ping command on the platform and returns a tuple consisting of: 1) the output string 2) the return code (0 is the expected return code) 3) parsed output from the ping command """ cmd = ["ping"] # Add the argument of the number of pings if system_name().lower() == "windows": cmd.extend(["-n", str(count)]) else: cmd.extend(["-c", str(count)]) # Add the host argument cmd.append(host) output = None return_code = None try: output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) return_code = 0 except subprocess.CalledProcessError as exception: output = exception.output return_code = exception.returncode except OSError as exception: if exception.errno == errno.ENOENT: raise CommandNotFoundException(cmd[0]) else: raise exception # Parse the output try: parsed = pingparser.parse(output) except Exception: parsed = {'message': 'output could not be parsed', 'output': output} # Write the event as a stash new file if index is not None: writer = StashNewWriter(index=index, source_name=source, sourcetype=sourcetype, file_extension=".stash_output") result = collections.OrderedDict() result.update(parsed) if 'host' in result: result['dest'] = result['host'] del result['host'] result['return_code'] = return_code result['output'] = output # Remove the jitter field on Windows since it doesn't get populated on Windows if 'jitter' in result and (result['jitter'] is None or len(result['jitter']) == 0): del result['jitter'] # Log that we performed the ping if logger: logger.debug("Wrote stash file=%s", writer.write_event(result)) return output, return_code, parsed