bool test_extract_ipv4(char* ipv6_as_string, int prefix_len) { const char expected_as_string[INET_ADDRSTRLEN] = "192.0.2.33"; struct in_addr expected; struct in_addr actual; struct in6_addr ipv6; if (!str_to_addr4(expected_as_string, &expected)) { log_warning("Can't parse expected IPv4 address '%s'. Failing test.", expected_as_string); return false; } if (!str_to_addr6(ipv6_as_string, &ipv6)) { log_warning("Can't parse IPv6 address being tested '%s'. Failing test.", ipv6_as_string); return false; } actual = nat64_extract_ipv4(&ipv6, prefix_len); ASSERT_EQUALS_IPV4(expected, actual, "Extract IPv4.") return true; }
/* * This procedure performs packet filtering and * updates BIBs and STs. */ static bool nat64_filtering_and_updating(u_int8_t l3protocol, u_int8_t l4protocol, struct sk_buff *skb, struct nf_conntrack_tuple * inner) { struct nat64_bib_entry *bib; struct nat64_st_entry *session; struct tcphdr *tcph = tcp_hdr(skb); //struct icmphdr *icmph = icmp_hdr(skb); bool res; int i; res = false; if (l3protocol == NFPROTO_IPV4) { pr_debug("NAT64: FNU - IPV4"); /* * Query the STs for any records * If there's no active session for the specified * connection, the packet should be dropped */ switch (l4protocol) { case IPPROTO_TCP: //Query TCP ST //pr_debug("NAT64: TCP protocol not currently supported."); bib = nat64_bib_ipv4_lookup((*inner).dst.u3.in.s_addr, inner->dst.u.tcp.port, IPPROTO_TCP); if (!bib) { pr_warning("NAT64: IPv4 - BIB is missing."); return res; } session = nat64_session_ipv4_lookup(bib, inner->src.u3.in.s_addr, inner->src.u.tcp.port); if (!session) { pr_warning("NAT64: IPv4 - session entry is " "missing."); return res; } pr_debug("NAT64: TCP protocol for IPv4 " "finished properly."); res = true; break; case IPPROTO_UDP: //Query UDP BIB and ST bib = nat64_bib_ipv4_lookup(inner->dst.u3.in.s_addr, (inner->dst.u.udp.port), IPPROTO_UDP); if (!bib) { pr_warning("NAT64: IPv4 - BIB is missing."); return res; } session = nat64_session_ipv4_lookup(bib, inner->src.u3.in.s_addr, inner->src.u.udp.port); if (!session) { pr_warning("NAT64: IPv4 - session entry is " "missing."); return res; } pr_debug("NAT64: UDP protocol for IPv4 " "finished properly."); res = true; break; case IPPROTO_ICMP: //Query ICMP ST bib = nat64_bib_ipv4_lookup(inner->dst.u3.in.s_addr, (inner->src.u.icmp.id), IPPROTO_ICMPV6); if (!bib) { pr_debug("No se pudo con T':%pI4.", &inner->dst.u3.in.s_addr); pr_debug("Inner: %hu", ntohs(inner->src.u.icmp.id)); pr_warning("NAT64: IPv4 - BIB is missing."); return res; } session = nat64_session_ipv4_lookup(bib, inner->src.u3.in.s_addr, inner->src.u.icmp.id); if (!session) { pr_warning("NAT64: IPv4 - session entry is " "missing."); return res; } res = true; break; case IPPROTO_ICMPV6: //Query ICMPV6 ST pr_debug("NAT64: ICMPv6 protocol not " "currently supported."); break; default: //Drop packet pr_debug("NAT64: layer 4 protocol not " "currently supported."); break; } goto end; } else if (l3protocol == NFPROTO_IPV6) { pr_debug("NAT64: FNU - IPV6"); // FIXME: Return true if it is not H&H. A special return code // will have to be added as a param in the future to handle it. res = false; nat64_clean_expired_sessions(&expiry_queue,i); for (i = 0; i < NUM_EXPIRY_QUEUES; i++) nat64_clean_expired_sessions(&expiry_base[i].queue, i); switch (l4protocol) { case IPPROTO_TCP: /* * FIXME: Finish TCP session handling */ pr_debug("NAT64: FNU - TCP"); bib = nat64_bib_ipv6_lookup(&(inner->src.u3.in6), inner->src.u.tcp.port, IPPROTO_TCP); if(bib) { session = nat64_session_ipv4_lookup(bib, nat64_extract_ipv4( inner->dst.u3.in6, //prefix_len), ipv6_pref_len), inner->dst.u.tcp.port); if(session) { nat64_tcp6_fsm(session, tcph); }else{ pr_debug("Create a session entry, no sesion."); session = nat64_session_create_tcp(bib, &(inner->dst.u3.in6), nat64_extract_ipv4( inner->dst.u3.in6, //prefix_len), ipv6_pref_len), inner->dst.u.tcp.port, TCP_TRANS); } } else if (tcph->syn) { pr_debug("Create a new BIB and Session entry syn."); bib = nat64_bib_session_create_tcp( &(inner->src.u3.in6), &(inner->dst.u3.in6), nat64_extract_ipv4( inner->dst.u3.in6, //prefix_len), ipv6_pref_len), inner->src.u.tcp.port, inner->dst.u.tcp.port, l4protocol, TCP_TRANS); session = list_entry(bib->sessions.next, struct nat64_st_entry, list); session->state = V6_SYN_RCV; } res = true; break; case IPPROTO_UDP: pr_debug("NAT64: FNU - UDP"); /* * Verify if there's any binding for the src * address by querying the UDP BIB. If there's a * binding, verify if there's a connection to the * specified destination by querying the UDP ST. * * In case these records are missing, they * should be created. */ bib = nat64_bib_ipv6_lookup(&(inner->src.u3.in6), inner->src.u.udp.port, IPPROTO_UDP); if (bib) { session = nat64_session_ipv4_lookup(bib, nat64_extract_ipv4( inner->dst.u3.in6, ipv6_pref_len), inner->dst.u.udp.port); if (session) { nat64_session_renew(session, UDP_DEFAULT); } else { session = nat64_session_create(bib, &(inner->dst.u3.in6), nat64_extract_ipv4( inner->dst.u3.in6, ipv6_pref_len), inner->dst.u.udp.port, UDP_DEFAULT); } } else { pr_debug("Create a new BIB and Session entry."); bib = nat64_bib_session_create( &(inner->src.u3.in6), &(inner->dst.u3.in6), nat64_extract_ipv4( inner->dst.u3.in6, ipv6_pref_len), inner->src.u.udp.port, inner->dst.u.udp.port, l4protocol, UDP_DEFAULT); } res = true; break; case IPPROTO_ICMP: //Query ICMP ST pr_debug("NAT64: ICMP protocol not currently " "supported."); break; case IPPROTO_ICMPV6: //Query ICMPV6 ST bib = nat64_bib_ipv6_lookup(&(inner->src.u3.in6), inner->src.u.icmp.id, IPPROTO_ICMP); if(bib) { session = nat64_session_ipv4_lookup(bib, nat64_extract_ipv4( inner->dst.u3.in6, //prefix_len), ipv6_pref_len), inner->src.u.icmp.id); if(session) { nat64_session_renew(session, ICMP_DEFAULT); }else { session = nat64_session_create_icmp(bib, &(inner->dst.u3.in6), nat64_extract_ipv4( inner->dst.u3.in6, ipv6_pref_len), inner->src.u.icmp.id, ICMP_DEFAULT); } } else { pr_debug("Create a new BIB and Session entry."); bib = nat64_bib_session_create_icmp( &(inner->src.u3.in6), &(inner->dst.u3.in6), nat64_extract_ipv4( inner->dst.u3.in6, ipv6_pref_len), inner->src.u.icmp.id, inner->src.u.icmp.id, l4protocol, ICMP_DEFAULT); } res = true; /*pr_debug("NAT64: ICMPv6 protocol not currently "*/ /*"supported.");*/ break; default: //Drop packet pr_debug("NAT64: layer 4 protocol not currently " "supported."); break; }