8 from atf_python.sys.net.vnet import IfaceFactory
9 from atf_python.sys.net.vnet import SingleVnetTestTemplate
10 from atf_python.sys.net.tools import ToolsHelper
11 from typing import List
12 from typing import Optional
14 logging.getLogger("scapy").setLevel(logging.CRITICAL)
15 import scapy.all as sc
18 def build_response_packet(echo, ip, icmp, oip_ihl, special):
19 icmp_id_seq_types = [0, 8, 13, 14, 15, 16, 17, 18, 37, 38]
22 load = echo[sc.ICMP].payload
23 oip[sc.IP].remove_payload()
24 oicmp[sc.ICMP].remove_payload()
27 # As if the original IP packet had these set
33 oip.options = ip.options
35 # Inner packet (oip) options
40 if special == "no-payload":
44 tcp = sc.TCP(sport=1234, dport=5678)
45 return ip / icmp / oip / tcp
48 udp = sc.UDP(sport=1234, dport=5678)
49 return ip / icmp / oip / udp
51 # Build a package with a timestamp of INT_MAX
52 # (time-warped package)
53 payload_no_timestamp = sc.bytes_hex(load)[16:]
54 load = (b"\xff" * 8) + sc.hex_bytes(payload_no_timestamp)
55 if special == "wrong":
56 # Build a package with a wrong last byte
57 payload_no_last_byte = sc.bytes_hex(load)[:-2]
58 load = (sc.hex_bytes(payload_no_last_byte)) + b"\x00"
59 if special == "not-mine":
60 # Modify the ICMP Identifier field
63 if icmp.type in icmp_id_seq_types:
64 pkt = ip / icmp / load
67 pkt = ip / icmp / oip / oicmp / load
71 def generate_ip_options(opts):
86 routers_zero = [0, 0, 0, 0, 0, 0, 0, 0, 0]
88 options = sc.IPOption(b"\x00")
90 options = sc.IPOption(b"\x01")
91 elif opts == "NOP-40":
92 options = sc.IPOption(b"\x01" * 40)
94 ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
95 options = sc.IPOption_RR(pointer=40, routers=routers)
96 elif opts == "RR-same":
97 ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
98 options = sc.IPOption_RR(pointer=3, routers=routers_zero)
99 elif opts == "RR-trunc":
100 ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
101 options = sc.IPOption_RR(length=7, routers=routers_zero)
103 ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
104 options = sc.IPOption_LSRR(routers=routers)
105 elif opts == "LSRR-trunc":
106 ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
107 options = sc.IPOption_LSRR(length=3, routers=routers_zero)
109 ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
110 options = sc.IPOption_SSRR(routers=routers)
111 elif opts == "SSRR-trunc":
112 ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
113 options = sc.IPOption_SSRR(length=3, routers=routers_zero)
115 ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
116 options = sc.IPOption(b"\x9f")
117 elif opts == "unk-40":
118 ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
119 options = sc.IPOption(b"\x9f" * 40)
127 # Avoid setting defaults on these arguments,
128 # as we want to set them explicitly in the tests
131 src: sc.scapy.fields.SourceIPField,
132 dst: sc.scapy.layers.inet.DestIPField,
133 icmp_type: sc.scapy.fields.ByteEnumField,
134 icmp_code: sc.scapy.fields.MultiEnumField,
136 ihl: Optional[sc.scapy.fields.BitField] = None,
137 flags: Optional[sc.scapy.fields.FlagsField] = None,
138 opts: Optional[str] = None,
139 oip_ihl: Optional[sc.scapy.fields.BitField] = None,
140 special: Optional[str] = None,
142 # Match names with <netinet/ip_icmp.h>
143 icmp_pptr: sc.scapy.fields.ByteField = 0,
144 icmp_gwaddr: sc.scapy.fields.IPField = "0.0.0.0",
145 icmp_nextmtu: sc.scapy.fields.ShortField = 0,
146 icmp_otime: sc.scapy.layers.inet.ICMPTimeStampField = 0,
147 icmp_rtime: sc.scapy.layers.inet.ICMPTimeStampField = 0,
148 icmp_ttime: sc.scapy.layers.inet.ICMPTimeStampField = 0,
149 icmp_mask: sc.scapy.fields.IPField = "0.0.0.0",
150 request: Optional[str] = None,
151 # Miscellaneous arguments
154 verbose: bool = True,
155 ) -> subprocess.CompletedProcess:
160 :param str iface: Interface to send packet to
161 :keyword src: Source packet IP
162 :type src: class:`scapy.fields.SourceIPField`
163 :keyword dst: Destination packet IP
164 :type dst: class:`scapy.layers.inet.DestIPField`
165 :keyword icmp_type: ICMP type
166 :type icmp_type: class:`scapy.fields.ByteEnumField`
167 :keyword icmp_code: ICMP code
168 :type icmp_code: class:`scapy.fields.MultiEnumField`
170 :keyword ihl: Internet Header Length, defaults to None
171 :type ihl: class:`scapy.fields.BitField`, optional
172 :keyword flags: IP flags - one of `DF`, `MF` or `evil`, defaults to None
173 :type flags: class:`scapy.fields.FlagsField`, optional
174 :keyword opts: Include IP options - one of `EOL`, `NOP`, `NOP-40`, `unk`,
175 `unk-40`, `RR`, `RR-same`, `RR-trunc`, `LSRR`, `LSRR-trunc`, `SSRR` or
176 `SSRR-trunc`, defaults to None
177 :type opts: str, optional
178 :keyword oip_ihl: Inner packet's Internet Header Length, defaults to None
179 :type oip_ihl: class:`scapy.fields.BitField`, optional
180 :keyword special: Send a special packet - one of `no-payload`, `not-mine`,
181 `tcp`, `udp`, `wrong` or `warp`, defaults to None
182 :type special: str, optional
183 :keyword icmp_pptr: ICMP pointer, defaults to 0
184 :type icmp_pptr: class:`scapy.fields.ByteField`
185 :keyword icmp_gwaddr: ICMP gateway IP address, defaults to "0.0.0.0"
186 :type icmp_gwaddr: class:`scapy.fields.IPField`
187 :keyword icmp_nextmtu: ICMP next MTU, defaults to 0
188 :type icmp_nextmtu: class:`scapy.fields.ShortField`
189 :keyword icmp_otime: ICMP originate timestamp, defaults to 0
190 :type icmp_otime: class:`scapy.layers.inet.ICMPTimeStampField`
191 :keyword icmp_rtime: ICMP receive timestamp, defaults to 0
192 :type icmp_rtime: class:`scapy.layers.inet.ICMPTimeStampField`
193 :keyword icmp_ttime: ICMP transmit timestamp, defaults to 0
194 :type icmp_ttime: class:`scapy.layers.inet.ICMPTimeStampField`
195 :keyword icmp_mask: ICMP address mask, defaults to "0.0.0.0"
196 :type icmp_mask: class:`scapy.fields.IPField`
197 :keyword request: Request type - one of `mask` or `timestamp`,
199 :type request: str, optional
200 :keyword count: Number of packets to send, defaults to 1
202 :keyword dup: Duplicate packets, defaults to `False`
204 :keyword verbose: Turn on/off verbosity, defaults to `True`
207 :return: A class:`subprocess.CompletedProcess` with the output from the
209 :rtype: class:`subprocess.CompletedProcess`
211 tun = sc.TunTapInterface(iface)
212 subprocess.run(["ifconfig", tun.iface, "up"], check=True)
213 subprocess.run(["ifconfig", tun.iface, src, dst], check=True)
214 ip_opts = generate_ip_options(opts)
215 ip = sc.IP(ihl=ihl, flags=flags, src=dst, dst=src, options=ip_opts)
225 if request == "mask":
227 if request == "timestamp":
242 with subprocess.Popen(
243 args=command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
245 for dummy in range(count):
251 seq=echo[sc.ICMP].seq,
258 nexthopmtu=icmp_nextmtu,
260 pkt = build_response_packet(echo, ip, icmp, oip_ihl, special)
264 stdout, stderr = ping.communicate()
265 return subprocess.CompletedProcess(
266 ping.args, ping.returncode, stdout, stderr
271 """Redact some elements of ping's output"""
272 pattern_replacements = [
273 ("localhost \([0-9]{1,3}(\.[0-9]{1,3}){3}\)", "localhost"),
274 ("from [0-9]{1,3}(\.[0-9]{1,3}){3}", "from"),
275 ("hlim=[0-9]*", "hlim="),
276 ("ttl=[0-9]*", "ttl="),
277 ("time=[0-9.-]*", "time="),
278 ("\(-[0-9\.]+[0-9]+ ms\)", "(- ms)"),
279 ("[0-9\.]+/[0-9.]+", "/"),
281 for pattern, repl in pattern_replacements:
282 output = re.sub(pattern, repl, output)
286 class TestPing(SingleVnetTestTemplate):
287 IPV6_PREFIXES: List[str] = ["2001:db8::1/64"]
288 IPV4_PREFIXES: List[str] = ["192.0.2.1/24"]
290 # Each param in testdata contains a dictionary with the command,
291 # and the expected outcome (returncode, redacted stdout, and stderr)
295 "args": "ping -4 -c1 -s56 -t1 localhost",
298 PING localhost: 56 data bytes
299 64 bytes from: icmp_seq=0 ttl= time= ms
301 --- localhost ping statistics ---
302 1 packets transmitted, 1 packets received, 0.0% packet loss
303 round-trip min/avg/max/stddev = /// ms
307 id="_4_c1_s56_t1_localhost",
311 "args": "ping -6 -c1 -s8 -t1 localhost",
314 PING6(56=40+8+8 bytes) ::1 --> ::1
315 16 bytes from ::1, icmp_seq=0 hlim= time= ms
317 --- localhost ping6 statistics ---
318 1 packets transmitted, 1 packets received, 0.0% packet loss
319 round-trip min/avg/max/std-dev = /// ms
323 id="_6_c1_s8_t1_localhost",
327 "args": "ping -A -c1 192.0.2.1",
330 PING 192.0.2.1 (192.0.2.1): 56 data bytes
331 64 bytes from: icmp_seq=0 ttl= time= ms
333 --- 192.0.2.1 ping statistics ---
334 1 packets transmitted, 1 packets received, 0.0% packet loss
335 round-trip min/avg/max/stddev = /// ms
339 id="_A_c1_192_0_2_1",
343 "args": "ping -A -c1 192.0.2.2",
346 PING 192.0.2.2 (192.0.2.2): 56 data bytes
348 --- 192.0.2.2 ping statistics ---
349 1 packets transmitted, 0 packets received, 100.0% packet loss
353 id="_A_c1_192_0_2_2",
357 "args": "ping -A -c1 2001:db8::1",
360 PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
361 16 bytes from 2001:db8::1, icmp_seq=0 hlim= time= ms
363 --- 2001:db8::1 ping6 statistics ---
364 1 packets transmitted, 1 packets received, 0.0% packet loss
365 round-trip min/avg/max/std-dev = /// ms
369 id="_A_c1_2001_db8__1",
373 "args": "ping -A -c1 2001:db8::2",
376 PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
378 --- 2001:db8::2 ping6 statistics ---
379 1 packets transmitted, 0 packets received, 100.0% packet loss
383 id="_A_c1_2001_db8__2",
387 "args": "ping -A -c3 192.0.2.1",
390 PING 192.0.2.1 (192.0.2.1): 56 data bytes
391 64 bytes from: icmp_seq=0 ttl= time= ms
392 64 bytes from: icmp_seq=1 ttl= time= ms
393 64 bytes from: icmp_seq=2 ttl= time= ms
395 --- 192.0.2.1 ping statistics ---
396 3 packets transmitted, 3 packets received, 0.0% packet loss
397 round-trip min/avg/max/stddev = /// ms
405 "args": "ping -A -c3 192.0.2.2",
408 \x07\x07PING 192.0.2.2 (192.0.2.2): 56 data bytes
410 --- 192.0.2.2 ping statistics ---
411 3 packets transmitted, 0 packets received, 100.0% packet loss
415 id="_A_c3_192_0_2_2",
419 "args": "ping -A -c3 2001:db8::1",
422 PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
423 16 bytes from 2001:db8::1, icmp_seq=0 hlim= time= ms
424 16 bytes from 2001:db8::1, icmp_seq=1 hlim= time= ms
425 16 bytes from 2001:db8::1, icmp_seq=2 hlim= time= ms
427 --- 2001:db8::1 ping6 statistics ---
428 3 packets transmitted, 3 packets received, 0.0% packet loss
429 round-trip min/avg/max/std-dev = /// ms
433 id="_A_c3_2001_db8__1",
437 "args": "ping -A -c3 2001:db8::2",
440 \x07\x07PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
442 --- 2001:db8::2 ping6 statistics ---
443 3 packets transmitted, 0 packets received, 100.0% packet loss
447 id="_A_c3_2001_db8__2",
451 "args": "ping -c1 192.0.2.1",
454 PING 192.0.2.1 (192.0.2.1): 56 data bytes
455 64 bytes from: icmp_seq=0 ttl= time= ms
457 --- 192.0.2.1 ping statistics ---
458 1 packets transmitted, 1 packets received, 0.0% packet loss
459 round-trip min/avg/max/stddev = /// ms
467 "args": "ping -c1 192.0.2.2",
470 PING 192.0.2.2 (192.0.2.2): 56 data bytes
472 --- 192.0.2.2 ping statistics ---
473 1 packets transmitted, 0 packets received, 100.0% packet loss
481 "args": "ping -c1 2001:db8::1",
484 PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
485 16 bytes from 2001:db8::1, icmp_seq=0 hlim= time= ms
487 --- 2001:db8::1 ping6 statistics ---
488 1 packets transmitted, 1 packets received, 0.0% packet loss
489 round-trip min/avg/max/std-dev = /// ms
493 id="_c1_2001_db8__1",
497 "args": "ping -c1 2001:db8::2",
500 PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
502 --- 2001:db8::2 ping6 statistics ---
503 1 packets transmitted, 0 packets received, 100.0% packet loss
507 id="_c1_2001_db8__2",
511 "args": "ping -c1 -S127.0.0.1 -s56 -t1 localhost",
514 PING localhost from: 56 data bytes
515 64 bytes from: icmp_seq=0 ttl= time= ms
517 --- localhost ping statistics ---
518 1 packets transmitted, 1 packets received, 0.0% packet loss
519 round-trip min/avg/max/stddev = /// ms
523 id="_c1_S127_0_0_1_s56_t1_localhost",
527 "args": "ping -c1 -S::1 -s8 -t1 localhost",
530 PING6(56=40+8+8 bytes) ::1 --> ::1
531 16 bytes from ::1, icmp_seq=0 hlim= time= ms
533 --- localhost ping6 statistics ---
534 1 packets transmitted, 1 packets received, 0.0% packet loss
535 round-trip min/avg/max/std-dev = /// ms
539 id="_c1_S__1_s8_t1_localhost",
543 "args": "ping -c3 192.0.2.1",
546 PING 192.0.2.1 (192.0.2.1): 56 data bytes
547 64 bytes from: icmp_seq=0 ttl= time= ms
548 64 bytes from: icmp_seq=1 ttl= time= ms
549 64 bytes from: icmp_seq=2 ttl= time= ms
551 --- 192.0.2.1 ping statistics ---
552 3 packets transmitted, 3 packets received, 0.0% packet loss
553 round-trip min/avg/max/stddev = /// ms
561 "args": "ping -c3 192.0.2.2",
564 PING 192.0.2.2 (192.0.2.2): 56 data bytes
566 --- 192.0.2.2 ping statistics ---
567 3 packets transmitted, 0 packets received, 100.0% packet loss
575 "args": "ping -c3 2001:db8::1",
578 PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
579 16 bytes from 2001:db8::1, icmp_seq=0 hlim= time= ms
580 16 bytes from 2001:db8::1, icmp_seq=1 hlim= time= ms
581 16 bytes from 2001:db8::1, icmp_seq=2 hlim= time= ms
583 --- 2001:db8::1 ping6 statistics ---
584 3 packets transmitted, 3 packets received, 0.0% packet loss
585 round-trip min/avg/max/std-dev = /// ms
589 id="_c3_2001_db8__1",
593 "args": "ping -c3 2001:db8::2",
596 PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
598 --- 2001:db8::2 ping6 statistics ---
599 3 packets transmitted, 0 packets received, 100.0% packet loss
603 id="_c3_2001_db8__2",
607 "args": "ping -q -c1 192.0.2.1",
610 PING 192.0.2.1 (192.0.2.1): 56 data bytes
612 --- 192.0.2.1 ping statistics ---
613 1 packets transmitted, 1 packets received, 0.0% packet loss
614 round-trip min/avg/max/stddev = /// ms
618 id="_q_c1_192_0_2_1",
622 "args": "ping -q -c1 192.0.2.2",
625 PING 192.0.2.2 (192.0.2.2): 56 data bytes
627 --- 192.0.2.2 ping statistics ---
628 1 packets transmitted, 0 packets received, 100.0% packet loss
632 id="_q_c1_192_0_2_2",
636 "args": "ping -q -c1 2001:db8::1",
639 PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
641 --- 2001:db8::1 ping6 statistics ---
642 1 packets transmitted, 1 packets received, 0.0% packet loss
643 round-trip min/avg/max/std-dev = /// ms
647 id="_q_c1_2001_db8__1",
651 "args": "ping -q -c1 2001:db8::2",
654 PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
656 --- 2001:db8::2 ping6 statistics ---
657 1 packets transmitted, 0 packets received, 100.0% packet loss
661 id="_q_c1_2001_db8__2",
665 "args": "ping -q -c3 192.0.2.1",
668 PING 192.0.2.1 (192.0.2.1): 56 data bytes
670 --- 192.0.2.1 ping statistics ---
671 3 packets transmitted, 3 packets received, 0.0% packet loss
672 round-trip min/avg/max/stddev = /// ms
676 id="_q_c3_192_0_2_1",
680 "args": "ping -q -c3 192.0.2.2",
683 PING 192.0.2.2 (192.0.2.2): 56 data bytes
685 --- 192.0.2.2 ping statistics ---
686 3 packets transmitted, 0 packets received, 100.0% packet loss
690 id="_q_c3_192_0_2_2",
694 "args": "ping -q -c3 2001:db8::1",
697 PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
699 --- 2001:db8::1 ping6 statistics ---
700 3 packets transmitted, 3 packets received, 0.0% packet loss
701 round-trip min/avg/max/std-dev = /// ms
705 id="_q_c3_2001_db8__1",
709 "args": "ping -q -c3 2001:db8::2",
712 PING6(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
714 --- 2001:db8::2 ping6 statistics ---
715 3 packets transmitted, 0 packets received, 100.0% packet loss
719 id="_q_c3_2001_db8__2",
723 @pytest.mark.parametrize("expected", testdata)
724 def test_ping(self, expected):
726 ping = subprocess.run(
727 expected["args"].split(),
732 assert ping.returncode == expected["returncode"]
733 assert redact(ping.stdout) == expected["stdout"]
734 assert ping.stderr == expected["stderr"]
736 # Each param in ping46_testdata contains a dictionary with the arguments
737 # and the expected outcome (returncode, redacted stdout, and stderr)
738 # common to `ping -4` and `ping -6`
742 "args": "-Wx localhost",
743 "returncode": os.EX_USAGE,
745 "stderr": "ping: invalid timing interval: `x'\n",
751 @pytest.mark.parametrize("expected", ping46_testdata)
752 def test_ping_46(self, expected):
753 """Test ping -4/ping -6"""
754 for version in [4, 6]:
755 ping = subprocess.run(
756 ["ping", f"-{version}"] + expected["args"].split(),
761 assert ping.returncode == expected["returncode"]
762 assert redact(ping.stdout) == expected["stdout"]
763 assert ping.stderr == expected["stderr"]
765 # Each param in pinger_testdata contains a dictionary with the keywords to
766 # `pinger()` and a dictionary with the expected outcome (returncode,
767 # stdout, stderr, and if ping's output is redacted)
779 PING 192.0.2.2 (192.0.2.2): 56 data bytes
780 64 bytes from: icmp_seq=0 ttl= time= ms
782 --- 192.0.2.2 ping statistics ---
783 1 packets transmitted, 1 packets received, 0.0% packet loss
784 round-trip min/avg/max/stddev = /// ms
802 PING 192.0.2.2 (192.0.2.2): 56 data bytes
803 64 bytes from: icmp_seq=0 ttl= time= ms
804 wrong total length 88 instead of 84
806 --- 192.0.2.2 ping statistics ---
807 1 packets transmitted, 1 packets received, 0.0% packet loss
808 round-trip min/avg/max/stddev = /// ms
826 PING 192.0.2.2 (192.0.2.2): 56 data bytes
827 64 bytes from: icmp_seq=0 ttl= time= ms
838 --- 192.0.2.2 ping statistics ---
839 1 packets transmitted, 1 packets received, 0.0% packet loss
840 round-trip min/avg/max/stddev = /// ms
853 "opts": "LSRR-trunc",
858 PING 192.0.2.2 (192.0.2.2): 56 data bytes
859 64 bytes from: icmp_seq=0 ttl= time= ms
860 LSRR: (truncated route)
863 --- 192.0.2.2 ping statistics ---
864 1 packets transmitted, 1 packets received, 0.0% packet loss
865 round-trip min/avg/max/stddev = /// ms
870 id="_0_0_opts_LSRR_trunc",
883 PING 192.0.2.2 (192.0.2.2): 56 data bytes
884 64 bytes from: icmp_seq=0 ttl= time= ms
895 --- 192.0.2.2 ping statistics ---
896 1 packets transmitted, 1 packets received, 0.0% packet loss
897 round-trip min/avg/max/stddev = /// ms
910 "opts": "SSRR-trunc",
915 PING 192.0.2.2 (192.0.2.2): 56 data bytes
916 64 bytes from: icmp_seq=0 ttl= time= ms
917 SSRR: (truncated route)
920 --- 192.0.2.2 ping statistics ---
921 1 packets transmitted, 1 packets received, 0.0% packet loss
922 round-trip min/avg/max/stddev = /// ms
927 id="_0_0_opts_SSRR_trunc",
940 PING 192.0.2.2 (192.0.2.2): 56 data bytes
941 64 bytes from: icmp_seq=0 ttl= time= ms
952 --- 192.0.2.2 ping statistics ---
953 1 packets transmitted, 1 packets received, 0.0% packet loss
954 round-trip min/avg/max/stddev = /// ms
972 PING 192.0.2.2 (192.0.2.2): 56 data bytes
973 64 bytes from: icmp_seq=0 ttl= time= ms (same route)
975 --- 192.0.2.2 ping statistics ---
976 1 packets transmitted, 1 packets received, 0.0% packet loss
977 round-trip min/avg/max/stddev = /// ms
982 id="_0_0_opts_RR_same",
995 PING 192.0.2.2 (192.0.2.2): 56 data bytes
996 64 bytes from: icmp_seq=0 ttl= time= ms
997 RR: (truncated route)
999 --- 192.0.2.2 ping statistics ---
1000 1 packets transmitted, 1 packets received, 0.0% packet loss
1001 round-trip min/avg/max/stddev = /// ms
1006 id="_0_0_opts_RR_trunc",
1019 PING 192.0.2.2 (192.0.2.2): 56 data bytes
1020 64 bytes from: icmp_seq=0 ttl= time= ms
1021 wrong total length 88 instead of 84
1024 --- 192.0.2.2 ping statistics ---
1025 1 packets transmitted, 1 packets received, 0.0% packet loss
1026 round-trip min/avg/max/stddev = /// ms
1044 PING 192.0.2.2 (192.0.2.2): 56 data bytes
1045 64 bytes from: icmp_seq=0 ttl= time= ms
1046 wrong total length 124 instead of 84
1088 --- 192.0.2.2 ping statistics ---
1089 1 packets transmitted, 1 packets received, 0.0% packet loss
1090 round-trip min/avg/max/stddev = /// ms
1095 id="_0_0_opts_NOP_40",
1108 PING 192.0.2.2 (192.0.2.2): 56 data bytes
1109 64 bytes from: icmp_seq=0 ttl= time= ms
1110 wrong total length 88 instead of 84
1113 --- 192.0.2.2 ping statistics ---
1114 1 packets transmitted, 1 packets received, 0.0% packet loss
1115 round-trip min/avg/max/stddev = /// ms
1133 PING 192.0.2.2 (192.0.2.2): 56 data bytes
1134 132 bytes from 192.0.2.2: Destination Host Unreachable
1135 Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
1136 4 f 00 007c 0001 0 0000 40 01 d868 192.0.2.1 192.0.2.2 01010101010101010101010101010101010101010101010101010101010101010101010101010101
1139 --- 192.0.2.2 ping statistics ---
1140 1 packets transmitted, 0 packets received, 100.0% packet loss
1145 id="_3_1_opts_NOP_40",
1158 PING 192.0.2.2 (192.0.2.2): 56 data bytes
1159 92 bytes from 192.0.2.2: Destination Host Unreachable
1160 Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
1161 4 5 00 0054 0001 2 0000 40 01 b6a4 192.0.2.1 192.0.2.2
1164 --- 192.0.2.2 ping statistics ---
1165 1 packets transmitted, 0 packets received, 100.0% packet loss
1184 PING 192.0.2.2 (192.0.2.2): 56 data bytes
1186 --- 192.0.2.2 ping statistics ---
1187 1 packets transmitted, 0 packets received, 100.0% packet loss
1190 ping: quoted data too short (40 bytes) from 192.0.2.2
1194 id="_3_1_special_tcp",
1208 PING 192.0.2.2 (192.0.2.2): 56 data bytes
1210 --- 192.0.2.2 ping statistics ---
1211 1 packets transmitted, 0 packets received, 100.0% packet loss
1214 ping: quoted data too short (28 bytes) from 192.0.2.2
1218 id="_3_1_special_udp",
1231 PING 192.0.2.2 (192.0.2.2): 56 data bytes
1232 92 bytes from 192.0.2.2: Destination Host Unreachable
1233 Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
1234 4 5 00 0054 0001 0 0000 40 01 f6a4 192.0.2.1 192.0.2.2
1237 --- 192.0.2.2 ping statistics ---
1238 1 packets transmitted, 0 packets received, 100.0% packet loss
1243 id="_3_1_verbose_false",
1251 "special": "not-mine",
1258 PING 192.0.2.2 (192.0.2.2): 56 data bytes
1260 --- 192.0.2.2 ping statistics ---
1261 1 packets transmitted, 0 packets received, 100.0% packet loss
1266 id="_3_1_special_not_mine_verbose_false",
1280 PING 192.0.2.2 (192.0.2.2): 56 data bytes
1281 64 bytes from: icmp_seq=0 ttl= time= ms
1283 --- 192.0.2.2 ping statistics ---
1284 1 packets transmitted, 1 packets received, 0.0% packet loss
1285 round-trip min/avg/max/stddev = /// ms
1288 ping: time of day goes back (- ms), clamping time to 0
1292 id="_0_0_special_warp",
1296 @pytest.mark.parametrize("pinger_kargs, expected", pinger_testdata)
1297 @pytest.mark.require_progs(["scapy"])
1298 @pytest.mark.require_user("root")
1299 def test_pinger(self, pinger_kargs, expected):
1300 """Test ping using pinger(), a reply faker"""
1301 iface = IfaceFactory().create_iface("", "tun")[0].name
1302 ping = pinger(iface, **pinger_kargs)
1303 assert ping.returncode == expected["returncode"]
1304 if expected["redacted"]:
1305 assert redact(ping.stdout) == expected["stdout"]
1306 assert redact(ping.stderr) == expected["stderr"]
1308 assert ping.stdout == expected["stdout"]
1309 assert ping.stderr == expected["stderr"]