def test_map_t_time_exceeded_ip4_to_ip6(self): """ MAP-T time exceeded IPv4 -> IPv6 """ eth = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) ip = IP(src=self.pg0.remote_ip4, dst=self.ipv4_map_address) icmp = ICMP(type="time-exceeded", code="ttl-zero-during-transit") ip_inner = IP(dst=self.pg0.remote_ip4, src=self.ipv4_map_address, ttl=1) udp_inner = UDP(sport=self.ipv4_udp_or_tcp_map_port, dport=self.ipv4_udp_or_tcp_internet_port) payload = "H" * 10 tx_pkt = eth / ip / icmp / ip_inner / udp_inner / payload self.pg_send(self.pg0, tx_pkt * 1) rx_pkts = self.pg1.get_capture(1) rx_pkt = rx_pkts[0] self.v6_address_check(rx_pkt) self.assertEqual(rx_pkt[IPv6].nh, IPv6(nh="ICMPv6").nh) self.assertEqual(rx_pkt[ICMPv6TimeExceeded].type, ICMPv6TimeExceeded().type) self.assertEqual( rx_pkt[ICMPv6TimeExceeded].code, ICMPv6TimeExceeded(code="hop limit exceeded in transit").code) self.assertEqual(rx_pkt[ICMPv6TimeExceeded].hlim, tx_pkt[IP][1].ttl) self.assertTrue(rx_pkt.haslayer(IPerror6)) self.assertTrue(rx_pkt.haslayer(UDPerror)) self.assertEqual(rx_pkt[IPv6].src, rx_pkt[IPerror6].dst) self.assertEqual(rx_pkt[IPv6].dst, rx_pkt[IPerror6].src) self.assertEqual(rx_pkt[UDPerror].sport, self.ipv6_udp_or_tcp_map_port) self.assertEqual(rx_pkt[UDPerror].dport, self.ipv6_udp_or_tcp_internet_port)
def test_map_t_time_exceeded_ip6_to_ip4(self): """ MAP-T time exceeded IPv6 -> IPv4 """ eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address) icmp = ICMPv6TimeExceeded() ip_inner = IPv6(src=self.ipv6_map_address, dst=self.ipv6_cpe_address, hlim=1) udp_inner = UDP(sport=self.ipv6_udp_or_tcp_internet_port, dport=self.ipv6_udp_or_tcp_map_port) payload = "H" * 10 tx_pkt = eth / ip / icmp / ip_inner / udp_inner / payload self.pg_send(self.pg1, tx_pkt * 1) rx_pkts = self.pg0.get_capture(1) rx_pkt = rx_pkts[0] self.v4_address_check(rx_pkt) self.assertEqual(rx_pkt[IP].proto, IP(proto="icmp").proto) self.assertEqual(rx_pkt[ICMP].type, ICMP(type="time-exceeded").type) self.assertEqual(rx_pkt[ICMP].code, ICMP(code="ttl-zero-during-transit").code) self.assertEqual(rx_pkt[ICMP].ttl, tx_pkt[IPv6][1].hlim) self.assertTrue(rx_pkt.haslayer(IPerror)) self.assertTrue(rx_pkt.haslayer(UDPerror)) self.assertEqual(rx_pkt[IP].src, rx_pkt[IPerror].dst) self.assertEqual(rx_pkt[IP].dst, rx_pkt[IPerror].src) self.assertEqual(rx_pkt[UDPerror].sport, self.ipv4_udp_or_tcp_internet_port) self.assertEqual(rx_pkt[UDPerror].dport, self.ipv4_udp_or_tcp_map_port)
def test_map_t(self): """ MAP-T """ # # Add a domain that maps from pg0 to pg1 # map_dst = '2001:db8::/32' map_src = '1234:5678:90ab:cdef::/64' ip4_pfx = '192.168.0.0/24' tag = 'MAP-T Tag.' self.vapi.map_add_domain(ip6_prefix=map_dst, ip4_prefix=ip4_pfx, ip6_src=map_src, ea_bits_len=16, psid_offset=6, psid_length=4, mtu=1500, tag=tag) # Enable MAP-T on interfaces. self.vapi.map_if_enable_disable(is_enable=1, sw_if_index=self.pg0.sw_if_index, is_translation=1) self.vapi.map_if_enable_disable(is_enable=1, sw_if_index=self.pg1.sw_if_index, is_translation=1) # Ensure MAP doesn't steal all packets! v4 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4) / UDP(sport=20000, dport=10000) / Raw(b'\xa5' * 100)) rx = self.send_and_expect(self.pg0, v4 * 1, self.pg0) v4_reply = v4[1] v4_reply.ttl -= 1 for p in rx: self.validate(p[1], v4_reply) # Ensure MAP doesn't steal all packets v6 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IPv6(src=self.pg1.remote_ip6, dst=self.pg1.remote_ip6) / UDP(sport=20000, dport=10000) / Raw(b'\xa5' * 100)) rx = self.send_and_expect(self.pg1, v6 * 1, self.pg1) v6_reply = v6[1] v6_reply.hlim -= 1 for p in rx: self.validate(p[1], v6_reply) map_route = VppIpRoute(self, "2001:db8::", 32, [ VppRoutePath(self.pg1.remote_ip6, self.pg1.sw_if_index, proto=DpoProto.DPO_PROTO_IP6) ]) map_route.add_vpp_config() # # Send a v4 packet that will be translated # p_ether = Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) p_ip4 = IP(src=self.pg0.remote_ip4, dst='192.168.0.1') payload = TCP(sport=0xabcd, dport=0xabcd) p4 = (p_ether / p_ip4 / payload) p6_translated = (IPv6(src="1234:5678:90ab:cdef:ac:1001:200:0", dst="2001:db8:1f0::c0a8:1:f") / payload) p6_translated.hlim -= 1 rx = self.send_and_expect(self.pg0, p4 * 1, self.pg1) for p in rx: self.validate(p[1], p6_translated) # Send back an IPv6 packet that will be "untranslated" p_ether6 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) p_ip6 = IPv6(src='2001:db8:1f0::c0a8:1:f', dst='1234:5678:90ab:cdef:ac:1001:200:0') p6 = (p_ether6 / p_ip6 / payload) p4_translated = (IP(src='192.168.0.1', dst=self.pg0.remote_ip4) / payload) p4_translated.id = 0 p4_translated.ttl -= 1 rx = self.send_and_expect(self.pg1, p6 * 1, self.pg0) for p in rx: self.validate(p[1], p4_translated) # IPv4 TTL ip4_ttl_expired = IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=0) p4 = (p_ether / ip4_ttl_expired / payload) icmp4_reply = ( IP(id=0, ttl=254, src=self.pg0.local_ip4, dst=self.pg0.remote_ip4) / ICMP(type='time-exceeded', code='ttl-zero-during-transit') / IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=0) / payload) rx = self.send_and_expect(self.pg0, p4 * 1, self.pg0) for p in rx: self.validate(p[1], icmp4_reply) ''' This one is broken, cause it would require hairpinning... # IPv4 TTL TTL1 ip4_ttl_expired = IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=1) p4 = (p_ether / ip4_ttl_expired / payload) icmp4_reply = IP(id=0, ttl=254, src=self.pg0.local_ip4, dst=self.pg0.remote_ip4) / \ ICMP(type='time-exceeded', code='ttl-zero-during-transit' ) / \ IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=0) / payload rx = self.send_and_expect(self.pg0, p4*1, self.pg0) for p in rx: self.validate(p[1], icmp4_reply) ''' # IPv6 Hop limit ip6_hlim_expired = IPv6(hlim=0, src='2001:db8:1ab::c0a8:1:ab', dst='1234:5678:90ab:cdef:ac:1001:200:0') p6 = (p_ether6 / ip6_hlim_expired / payload) icmp6_reply = (IPv6( hlim=255, src=self.pg1.local_ip6, dst="2001:db8:1ab::c0a8:1:ab") / ICMPv6TimeExceeded(code=0) / IPv6(src="2001:db8:1ab::c0a8:1:ab", dst='1234:5678:90ab:cdef:ac:1001:200:0', hlim=0) / payload) rx = self.send_and_expect(self.pg1, p6 * 1, self.pg1) for p in rx: self.validate(p[1], icmp6_reply) # IPv4 Well-known port p_ip4 = IP(src=self.pg0.remote_ip4, dst='192.168.0.1') payload = UDP(sport=200, dport=200) p4 = (p_ether / p_ip4 / payload) self.send_and_assert_no_replies(self.pg0, p4 * 1) # IPv6 Well-known port payload = UDP(sport=200, dport=200) p6 = (p_ether6 / p_ip6 / payload) self.send_and_assert_no_replies(self.pg1, p6 * 1) # Packet fragmentation payload = UDP(sport=40000, dport=4000) / self.payload(1453) p4 = (p_ether / p_ip4 / payload) self.pg_enable_capture() self.pg0.add_stream(p4) self.pg_start() rx = self.pg1.get_capture(2) for p in rx: pass # TODO: Manual validation # self.validate(p[1], icmp4_reply) # Packet fragmentation send fragments payload = UDP(sport=40000, dport=4000) / self.payload(1453) p4 = (p_ether / p_ip4 / payload) frags = fragment(p4, fragsize=1000) self.pg_enable_capture() self.pg0.add_stream(frags) self.pg_start() rx = self.pg1.get_capture(2) for p in rx: pass # p.show2() # reass_pkt = reassemble(rx) # p4_reply.ttl -= 1 # p4_reply.id = 256 # self.validate(reass_pkt, p4_reply) # TCP MSS clamping self.vapi.map_param_set_tcp(1300) # # Send a v4 TCP SYN packet that will be translated and MSS clamped # p_ether = Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) p_ip4 = IP(src=self.pg0.remote_ip4, dst='192.168.0.1') payload = TCP(sport=0xabcd, dport=0xabcd, flags="S", options=[('MSS', 1460)]) p4 = (p_ether / p_ip4 / payload) p6_translated = (IPv6(src="1234:5678:90ab:cdef:ac:1001:200:0", dst="2001:db8:1f0::c0a8:1:f") / payload) p6_translated.hlim -= 1 p6_translated[TCP].options = [('MSS', 1300)] rx = self.send_and_expect(self.pg0, p4 * 1, self.pg1) for p in rx: self.validate(p[1], p6_translated) # Send back an IPv6 packet that will be "untranslated" p_ether6 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) p_ip6 = IPv6(src='2001:db8:1f0::c0a8:1:f', dst='1234:5678:90ab:cdef:ac:1001:200:0') p6 = (p_ether6 / p_ip6 / payload) p4_translated = (IP(src='192.168.0.1', dst=self.pg0.remote_ip4) / payload) p4_translated.id = 0 p4_translated.ttl -= 1 p4_translated[TCP].options = [('MSS', 1300)] rx = self.send_and_expect(self.pg1, p6 * 1, self.pg0) for p in rx: self.validate(p[1], p4_translated)
def test_map_t(self): """MAP-T""" # # Add a domain that maps from pg0 to pg1 # map_dst = "2001:db8::/32" map_src = "1234:5678:90ab:cdef::/64" ip4_pfx = "192.168.0.0/24" tag = "MAP-T Tag." self.vapi.map_add_domain( ip6_prefix=map_dst, ip4_prefix=ip4_pfx, ip6_src=map_src, ea_bits_len=16, psid_offset=6, psid_length=4, mtu=1500, tag=tag, ) # Enable MAP-T on interfaces. self.vapi.map_if_enable_disable(is_enable=1, sw_if_index=self.pg0.sw_if_index, is_translation=1) self.vapi.map_if_enable_disable(is_enable=1, sw_if_index=self.pg1.sw_if_index, is_translation=1) # Ensure MAP doesn't steal all packets! v4 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4) / UDP(sport=20000, dport=10000) / Raw(b"\xa5" * 100)) rx = self.send_and_expect(self.pg0, v4 * 1, self.pg0) v4_reply = v4[1] v4_reply.ttl -= 1 for p in rx: self.validate(p[1], v4_reply) # Ensure MAP doesn't steal all packets v6 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IPv6(src=self.pg1.remote_ip6, dst=self.pg1.remote_ip6) / UDP(sport=20000, dport=10000) / Raw(b"\xa5" * 100)) rx = self.send_and_expect(self.pg1, v6 * 1, self.pg1) v6_reply = v6[1] v6_reply.hlim -= 1 for p in rx: self.validate(p[1], v6_reply) map_route = VppIpRoute( self, "2001:db8::", 32, [ VppRoutePath( self.pg1.remote_ip6, self.pg1.sw_if_index, proto=DpoProto.DPO_PROTO_IP6, ) ], ) map_route.add_vpp_config() # # Send a v4 packet that will be translated # p_ether = Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) p_ip4 = IP(src=self.pg0.remote_ip4, dst="192.168.0.1") payload = TCP(sport=0xABCD, dport=0xABCD) p4 = p_ether / p_ip4 / payload p6_translated = (IPv6(src="1234:5678:90ab:cdef:ac:1001:200:0", dst="2001:db8:1f0::c0a8:1:f") / payload) p6_translated.hlim -= 1 rx = self.send_and_expect(self.pg0, p4 * 1, self.pg1) for p in rx: self.validate(p[1], p6_translated) # Send back an IPv6 packet that will be "untranslated" p_ether6 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) p_ip6 = IPv6(src="2001:db8:1f0::c0a8:1:f", dst="1234:5678:90ab:cdef:ac:1001:200:0") p6 = p_ether6 / p_ip6 / payload p4_translated = IP(src="192.168.0.1", dst=self.pg0.remote_ip4) / payload p4_translated.id = 0 p4_translated.ttl -= 1 rx = self.send_and_expect(self.pg1, p6 * 1, self.pg0) for p in rx: self.validate(p[1], p4_translated) # IPv4 TTL=0 ip4_ttl_expired = IP(src=self.pg0.remote_ip4, dst="192.168.0.1", ttl=0) p4 = p_ether / ip4_ttl_expired / payload icmp4_reply = ( IP(id=0, ttl=254, src=self.pg0.local_ip4, dst=self.pg0.remote_ip4) / ICMP(type="time-exceeded", code="ttl-zero-during-transit") / IP(src=self.pg0.remote_ip4, dst="192.168.0.1", ttl=0) / payload) rx = self.send_and_expect(self.pg0, p4 * 1, self.pg0) for p in rx: self.validate(p[1], icmp4_reply) # IPv4 TTL=1 ip4_ttl_expired = IP(src=self.pg0.remote_ip4, dst="192.168.0.1", ttl=1) p4 = p_ether / ip4_ttl_expired / payload icmp4_reply = ( IP(id=0, ttl=254, src=self.pg0.local_ip4, dst=self.pg0.remote_ip4) / ICMP(type="time-exceeded", code="ttl-zero-during-transit") / IP(src=self.pg0.remote_ip4, dst="192.168.0.1", ttl=1) / payload) rx = self.send_and_expect(self.pg0, p4 * 1, self.pg0) for p in rx: self.validate(p[1], icmp4_reply) # IPv6 Hop limit at BR ip6_hlim_expired = IPv6( hlim=1, src="2001:db8:1ab::c0a8:1:ab", dst="1234:5678:90ab:cdef:ac:1001:200:0", ) p6 = p_ether6 / ip6_hlim_expired / payload icmp6_reply = (IPv6( hlim=255, src=self.pg1.local_ip6, dst="2001:db8:1ab::c0a8:1:ab") / ICMPv6TimeExceeded(code=0) / IPv6( src="2001:db8:1ab::c0a8:1:ab", dst="1234:5678:90ab:cdef:ac:1001:200:0", hlim=1, ) / payload) rx = self.send_and_expect(self.pg1, p6 * 1, self.pg1) for p in rx: self.validate(p[1], icmp6_reply) # IPv6 Hop limit beyond BR ip6_hlim_expired = IPv6( hlim=0, src="2001:db8:1ab::c0a8:1:ab", dst="1234:5678:90ab:cdef:ac:1001:200:0", ) p6 = p_ether6 / ip6_hlim_expired / payload icmp6_reply = (IPv6( hlim=255, src=self.pg1.local_ip6, dst="2001:db8:1ab::c0a8:1:ab") / ICMPv6TimeExceeded(code=0) / IPv6( src="2001:db8:1ab::c0a8:1:ab", dst="1234:5678:90ab:cdef:ac:1001:200:0", hlim=0, ) / payload) rx = self.send_and_expect(self.pg1, p6 * 1, self.pg1) for p in rx: self.validate(p[1], icmp6_reply) # IPv4 Well-known port p_ip4 = IP(src=self.pg0.remote_ip4, dst="192.168.0.1") payload = UDP(sport=200, dport=200) p4 = p_ether / p_ip4 / payload self.send_and_assert_no_replies(self.pg0, p4 * 1) # IPv6 Well-known port payload = UDP(sport=200, dport=200) p6 = p_ether6 / p_ip6 / payload self.send_and_assert_no_replies(self.pg1, p6 * 1) # UDP packet fragmentation payload_len = 1453 payload = UDP(sport=40000, dport=4000) / self.payload(payload_len) p4 = p_ether / p_ip4 / payload self.pg_enable_capture() self.pg0.add_stream(p4) self.pg_start() rx = self.pg1.get_capture(2) p_ip6_translated = IPv6(src="1234:5678:90ab:cdef:ac:1001:200:0", dst="2001:db8:1e0::c0a8:1:e") for p in rx: self.validate_frag6(p, p_ip6_translated) self.validate_frag_payload_len6(rx, UDP, payload_len) # UDP packet fragmentation send fragments payload_len = 1453 payload = UDP(sport=40000, dport=4000) / self.payload(payload_len) p4 = p_ether / p_ip4 / payload frags = fragment_rfc791(p4, fragsize=1000) self.pg_enable_capture() self.pg0.add_stream(frags) self.pg_start() rx = self.pg1.get_capture(2) for p in rx: self.validate_frag6(p, p_ip6_translated) self.validate_frag_payload_len6(rx, UDP, payload_len) # Send back an fragmented IPv6 UDP packet that will be "untranslated" payload = UDP(sport=4000, dport=40000) / self.payload(payload_len) p_ether6 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) p_ip6 = IPv6(src="2001:db8:1e0::c0a8:1:e", dst="1234:5678:90ab:cdef:ac:1001:200:0") p6 = p_ether6 / p_ip6 / payload frags6 = fragment_rfc8200(p6, identification=0xDCBA, fragsize=1000) p_ip4_translated = IP(src="192.168.0.1", dst=self.pg0.remote_ip4) p4_translated = p_ip4_translated / payload p4_translated.id = 0 p4_translated.ttl -= 1 self.pg_enable_capture() self.pg1.add_stream(frags6) self.pg_start() rx = self.pg0.get_capture(2) for p in rx: self.validate_frag4(p, p4_translated) self.validate_frag_payload_len4(rx, UDP, payload_len) # ICMP packet fragmentation payload = ICMP(id=6529) / self.payload(payload_len) p4 = p_ether / p_ip4 / payload self.pg_enable_capture() self.pg0.add_stream(p4) self.pg_start() rx = self.pg1.get_capture(2) p_ip6_translated = IPv6(src="1234:5678:90ab:cdef:ac:1001:200:0", dst="2001:db8:160::c0a8:1:6") for p in rx: self.validate_frag6(p, p_ip6_translated) self.validate_frag_payload_len6(rx, ICMPv6EchoRequest, payload_len) # ICMP packet fragmentation send fragments payload = ICMP(id=6529) / self.payload(payload_len) p4 = p_ether / p_ip4 / payload frags = fragment_rfc791(p4, fragsize=1000) self.pg_enable_capture() self.pg0.add_stream(frags) self.pg_start() rx = self.pg1.get_capture(2) for p in rx: self.validate_frag6(p, p_ip6_translated) self.validate_frag_payload_len6(rx, ICMPv6EchoRequest, payload_len) # TCP MSS clamping self.vapi.map_param_set_tcp(1300) # # Send a v4 TCP SYN packet that will be translated and MSS clamped # p_ether = Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) p_ip4 = IP(src=self.pg0.remote_ip4, dst="192.168.0.1") payload = TCP(sport=0xABCD, dport=0xABCD, flags="S", options=[("MSS", 1460)]) p4 = p_ether / p_ip4 / payload p6_translated = (IPv6(src="1234:5678:90ab:cdef:ac:1001:200:0", dst="2001:db8:1f0::c0a8:1:f") / payload) p6_translated.hlim -= 1 p6_translated[TCP].options = [("MSS", 1300)] rx = self.send_and_expect(self.pg0, p4 * 1, self.pg1) for p in rx: self.validate(p[1], p6_translated) # Send back an IPv6 packet that will be "untranslated" p_ether6 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) p_ip6 = IPv6(src="2001:db8:1f0::c0a8:1:f", dst="1234:5678:90ab:cdef:ac:1001:200:0") p6 = p_ether6 / p_ip6 / payload p4_translated = IP(src="192.168.0.1", dst=self.pg0.remote_ip4) / payload p4_translated.id = 0 p4_translated.ttl -= 1 p4_translated[TCP].options = [("MSS", 1300)] rx = self.send_and_expect(self.pg1, p6 * 1, self.pg0) for p in rx: self.validate(p[1], p4_translated) # TCP MSS clamping cleanup self.vapi.map_param_set_tcp(0) # Enable icmp6 param to get back ICMPv6 unreachable messages in case # of security check fails self.vapi.map_param_set_icmp6(enable_unreachable=1) # Send back an IPv6 packet that will be droppped due to security # check fail p_ether6 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) p_ip6_sec_check_fail = IPv6(src="2001:db8:1fe::c0a8:1:f", dst="1234:5678:90ab:cdef:ac:1001:200:0") payload = TCP(sport=0xABCD, dport=0xABCD) p6 = p_ether6 / p_ip6_sec_check_fail / payload self.pg_send(self.pg1, p6 * 1) self.pg0.get_capture(0, timeout=1) rx = self.pg1.get_capture(1) icmp6_reply = (IPv6( hlim=255, src=self.pg1.local_ip6, dst="2001:db8:1fe::c0a8:1:f") / ICMPv6DestUnreach(code=5) / p_ip6_sec_check_fail / payload) for p in rx: self.validate(p[1], icmp6_reply) # ICMPv6 unreachable messages cleanup self.vapi.map_param_set_icmp6(enable_unreachable=0)
def test_map_t(self): """ MAP-T """ # # Add a domain that maps from pg0 to pg1 # self.vapi.map_add_domain('2001:db8::/32', '1234:5678:90ab:cdef::/64', '192.168.0.0/24', 16, 6, 4, 1) # Enable MAP-T on interfaces. # self.vapi.map_if_enable_disable(1, self.pg0.sw_if_index, 1) # self.vapi.map_if_enable_disable(1, self.pg1.sw_if_index, 1) map_route = VppIpRoute(self, "2001:db8::", 32, [VppRoutePath(self.pg1.remote_ip6, self.pg1.sw_if_index, proto=DpoProto.DPO_PROTO_IP6)], is_ip6=1) map_route.add_vpp_config() # # Send a v4 packet that will be translated # p_ether = Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) p_ip4 = IP(src=self.pg0.remote_ip4, dst='192.168.0.1') payload = TCP(sport=0xabcd, dport=0xabcd) p4 = (p_ether / p_ip4 / payload) p6_translated = (IPv6(src="1234:5678:90ab:cdef:ac:1001:200:0", dst="2001:db8:1f0::c0a8:1:f") / payload) p6_translated.hlim -= 1 rx = self.send_and_expect(self.pg0, p4*1, self.pg1) for p in rx: self.validate(p[1], p6_translated) # Send back an IPv6 packet that will be "untranslated" p_ether6 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) p_ip6 = IPv6(src='2001:db8:1f0::c0a8:1:f', dst='1234:5678:90ab:cdef:ac:1001:200:0') p6 = (p_ether6 / p_ip6 / payload) p4_translated = (IP(src='192.168.0.1', dst=self.pg0.remote_ip4) / payload) p4_translated.id = 0 p4_translated.ttl -= 1 rx = self.send_and_expect(self.pg1, p6*1, self.pg0) for p in rx: self.validate(p[1], p4_translated) # IPv4 TTL ip4_ttl_expired = IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=0) p4 = (p_ether / ip4_ttl_expired / payload) icmp4_reply = (IP(id=0, ttl=254, src=self.pg0.local_ip4, dst=self.pg0.remote_ip4) / ICMP(type='time-exceeded', code='ttl-zero-during-transit') / IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=0) / payload) rx = self.send_and_expect(self.pg0, p4*1, self.pg0) for p in rx: self.validate(p[1], icmp4_reply) ''' This one is broken, cause it would require hairpinning... # IPv4 TTL TTL1 ip4_ttl_expired = IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=1) p4 = (p_ether / ip4_ttl_expired / payload) icmp4_reply = IP(id=0, ttl=254, src=self.pg0.local_ip4, dst=self.pg0.remote_ip4) / \ ICMP(type='time-exceeded', code='ttl-zero-during-transit' ) / \ IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=0) / payload rx = self.send_and_expect(self.pg0, p4*1, self.pg0) for p in rx: self.validate(p[1], icmp4_reply) ''' # IPv6 Hop limit ip6_hlim_expired = IPv6(hlim=0, src='2001:db8:1ab::c0a8:1:ab', dst='1234:5678:90ab:cdef:ac:1001:200:0') p6 = (p_ether6 / ip6_hlim_expired / payload) icmp6_reply = (IPv6(hlim=255, src=self.pg1.local_ip6, dst="2001:db8:1ab::c0a8:1:ab") / ICMPv6TimeExceeded(code=0) / IPv6(src="2001:db8:1ab::c0a8:1:ab", dst='1234:5678:90ab:cdef:ac:1001:200:0', hlim=0) / payload) rx = self.send_and_expect(self.pg1, p6*1, self.pg1) for p in rx: self.validate(p[1], icmp6_reply) # IPv4 Well-known port p_ip4 = IP(src=self.pg0.remote_ip4, dst='192.168.0.1') payload = UDP(sport=200, dport=200) p4 = (p_ether / p_ip4 / payload) self.send_and_assert_no_replies(self.pg0, p4*1) # IPv6 Well-known port payload = UDP(sport=200, dport=200) p6 = (p_ether6 / p_ip6 / payload) self.send_and_assert_no_replies(self.pg1, p6*1) # Packet fragmentation payload = UDP(sport=40000, dport=4000) / self.payload(1453) p4 = (p_ether / p_ip4 / payload) self.pg_enable_capture() self.pg0.add_stream(p4) self.pg_start() rx = self.pg1.get_capture(2) for p in rx: pass # TODO: Manual validation # self.validate(p[1], icmp4_reply) # Packet fragmentation send fragments payload = UDP(sport=40000, dport=4000) / self.payload(1453) p4 = (p_ether / p_ip4 / payload) frags = fragment(p4, fragsize=1000) self.pg_enable_capture() self.pg0.add_stream(frags) self.pg_start() rx = self.pg1.get_capture(2) for p in rx: pass