コード例 #1
0
ファイル: nf_nat64_session.c プロジェクト: credil/ecdysis
struct nat64_session *
nat64_ipv4_icmp_session(struct iphdr *ip4, struct icmphdr *icmp4, int recur)
{
	struct nat64_binding	 bkey;
	struct nat64_session	 skey;
	struct nat64_session	*s;

	memset(&bkey, 0, sizeof(bkey));
	memset(&skey, 0, sizeof(skey));

	skey.s_binding = &bkey;

	bkey.b_proto  = IPPROTO_ICMP;
	bkey.b_saddr4.s_addr = recur % 2 ? ip4->saddr : ip4->daddr;
	bkey.b_sport4 = icmp4->un.echo.id;
	skey.s_daddr.s_addr  = recur % 2 ? ip4->daddr : ip4->saddr;
	skey.s_dport  = icmp4->un.echo.id;

	s = nat64_session_by_ipv4_find(&skey);

	if (recur)
		return s;

	if (!s) {
		if (!(skey.s_binding = nat64_binding_by_ipv4_find(&bkey)))
			/* TODO send ICMP unreachable */
			return NULL;

		if (!(s = nat64_session_create(&skey)))
			return NULL;
	}

	nat64_session_refresh(s, 5*60);

	return s;
}
コード例 #2
0
ファイル: nf_nat64_session.c プロジェクト: credil/ecdysis
struct nat64_session *
nat64_ipv4_tcp_session(struct iphdr *ip4, struct tcphdr *th, int recur)
{
	struct nat64_binding	 bkey;
	struct nat64_session	 skey;
	struct nat64_session	*s;

	memset(&bkey, 0, sizeof(bkey));
	memset(&skey, 0, sizeof(skey));

	skey.s_binding = &bkey;

	bkey.b_proto  = IPPROTO_TCP;
	bkey.b_saddr4.s_addr = recur % 2 ? ip4->saddr : ip4->daddr;
	bkey.b_sport4 = recur % 2 ? th->source : th->dest;
	skey.s_daddr.s_addr  = recur % 2 ? ip4->daddr : ip4->saddr;
	skey.s_dport  = recur % 2 ? th->dest : th->source;

	s = nat64_session_by_ipv4_find(&skey);

	if (recur)
		return s;

	if (!s) {
		if (!th->syn)
			return NULL;

		skey.s_state = nat64_session_state_tcp_v4_syn_rcv;
		if (!(skey.s_binding = nat64_binding_by_ipv4_find(&bkey)))
			/* TODO send ICMP unreachable */
			return NULL;

		if (!(s = nat64_session_create(&skey)))
			return NULL;

		nat64_session_refresh(s, 6);

		return NULL;
	}

	switch (s->s_state) {

	case nat64_session_state_tcp_v4_syn_rcv:
		return s;

	case nat64_session_state_tcp_v6_syn_rcv:
		if (!th->syn)
			return s;

		s->s_state = nat64_session_state_tcp_established;
		nat64_session_refresh(s, 2*60*60 + 4*60);
		return s;

	case nat64_session_state_tcp_established:
		if (th->rst) {
			s->s_state = nat64_session_state_tcp_rst_rcv;
			nat64_session_refresh(s, 4*60);
		} else {
			if (th->fin)
				s->s_state = nat64_session_state_tcp_v4_fin_rcv;
			nat64_session_refresh(s, 2*60*60 + 4*60);
		}
		return s;

	case nat64_session_state_tcp_v4_fin_rcv:
		nat64_session_refresh(s, 2*60*60 + 4*60);
		return s;

	case nat64_session_state_tcp_v6_fin_rcv:
		if (th->fin) {
			s->s_state = nat64_session_state_tcp_v6_v4_fin_rcv;
			nat64_session_refresh(s, 4*60);
		} else
			nat64_session_refresh(s, 2*60*60 + 4*60);
		return s;

	case nat64_session_state_tcp_v6_v4_fin_rcv:
		return s;

	case nat64_session_state_tcp_rst_rcv:
		s->s_state = nat64_session_state_tcp_established;
		nat64_session_refresh(s, 2*60*60 + 4*60);
		return s;

	default:
		WARN_ON_ONCE(1);
	}

	return NULL;  /* DROP */
}
コード例 #3
0
/*
 * 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;
        }