Example #1
0
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;
        }