Exemple #1
0
int nl_update_conntrack(struct nfct_handle *h,
			const struct nf_conntrack *orig,
			int timeout)
{
	int ret;
	struct nf_conntrack *ct;

	ct = nfct_clone(orig);
	if (ct == NULL)
		return -1;

	if (timeout > 0)
		nfct_set_attr_u32(ct, ATTR_TIMEOUT, timeout);

	/* unset NAT info, otherwise we hit error */
	nfct_attr_unset(ct, ATTR_SNAT_IPV4);
	nfct_attr_unset(ct, ATTR_DNAT_IPV4);
	nfct_attr_unset(ct, ATTR_SNAT_PORT);
	nfct_attr_unset(ct, ATTR_DNAT_PORT);

	if (nfct_attr_is_set(ct, ATTR_STATUS)) {
		uint32_t status = nfct_get_attr_u32(ct, ATTR_STATUS);
		status &= ~IPS_NAT_MASK;
		nfct_set_attr_u32(ct, ATTR_STATUS, status);
	}
	/* we have to unset the helper to avoid EBUSY in reset timers */
	if (nfct_attr_is_set(ct, ATTR_HELPER_NAME))
		nfct_attr_unset(ct, ATTR_HELPER_NAME);

	/* we hit error if we try to update the master conntrack */
	if (ct_is_related(ct)) {
		nfct_attr_unset(ct, ATTR_MASTER_L3PROTO);
		nfct_attr_unset(ct, ATTR_MASTER_L4PROTO);
		nfct_attr_unset(ct, ATTR_MASTER_IPV4_SRC);
		nfct_attr_unset(ct, ATTR_MASTER_IPV4_DST);
		nfct_attr_unset(ct, ATTR_MASTER_IPV6_SRC);
		nfct_attr_unset(ct, ATTR_MASTER_IPV6_DST);
		nfct_attr_unset(ct, ATTR_MASTER_PORT_SRC);
		nfct_attr_unset(ct, ATTR_MASTER_PORT_DST);
	}

	/* disable TCP window tracking for recovered connections if required */
	if (nfct_attr_is_set(ct, ATTR_TCP_STATE)) {
		uint8_t flags = IP_CT_TCP_FLAG_SACK_PERM;

		if (!CONFIG(sync).tcp_window_tracking)
			flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
		else
			flags |= IP_CT_TCP_FLAG_WINDOW_SCALE;

		/* FIXME: workaround, we should send TCP flags in updates */
		if (nfct_get_attr_u8(ct, ATTR_TCP_STATE) >=
						TCP_CONNTRACK_TIME_WAIT) {
			flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
		}
		nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_ORIG, flags);
		nfct_set_attr_u8(ct, ATTR_TCP_MASK_ORIG, flags);
		nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_REPL, flags);
		nfct_set_attr_u8(ct, ATTR_TCP_MASK_REPL, flags);
	}

	ret = nfct_query(h, NFCT_Q_UPDATE, ct);
	nfct_destroy(ct);

	return ret;
}
Exemple #2
0
static int
rpc_helper_cb(struct pkt_buff *pkt, uint32_t protoff,
	      struct myct *myct, uint32_t ctinfo)
{
	int dir = CTINFO2DIR(ctinfo);
	unsigned int offset = protoff, datalen;
	uint32_t *data, *port_ptr = NULL, xid;
	uint16_t port;
	uint8_t proto = nfct_get_attr_u8(myct->ct, ATTR_L4PROTO);
	enum msg_type rm_dir;
	struct rpc_info *rpc_info = myct->priv_data;
	union nfct_attr_grp_addr addr, daddr;
	struct nf_expect *exp = NULL;
	int ret = NF_ACCEPT;

	/* Until there's been traffic both ways, don't look into TCP packets. */
	if (proto == IPPROTO_TCP
	    && ctinfo != IP_CT_ESTABLISHED
	    && ctinfo != IP_CT_ESTABLISHED_REPLY) {
		pr_debug("TCP RPC: Conntrackinfo = %u\n", ctinfo);
		return ret;
	}
	if (proto == IPPROTO_TCP) {
		struct tcphdr *th =
			(struct tcphdr *) (pktb_network_header(pkt) + protoff);
		offset += th->doff * 4;
	} else {
		offset += sizeof(struct udphdr);
	}
	/* Skip broken headers */
	if (offset % 4) {
		pr_debug("RPC: broken header: offset %u%%4 != 0\n", offset);
		return ret;
	}

	/* Take into Record Fragment header */
	if (proto == IPPROTO_TCP)
		offset += 4;

	datalen = pktb_len(pkt);
	data = (uint32_t *)(pktb_network_header(pkt) + offset);

	/* rpc_msg {
	 *	xid
	 *	direction
	 *	xdr_union {
	 *		call_body
	 *		reply_body
	 *	}
	 * }
	 */

	 /* Check minimal msg size: xid + direction */
	if (datalen < OFFSET(offset, 2*4)) {
		pr_debug("RPC: too short packet: %u < %u\n",
			 datalen, offset);
		return ret;
	}
	xid = IXDR_GET_INT32(data);
	rm_dir = IXDR_GET_INT32(data);

	/* Check direction */
	if (!((rm_dir == CALL && dir == MYCT_DIR_ORIG)
	      || (rm_dir == REPLY && dir == MYCT_DIR_REPL))) {
		pr_debug("RPC: rm_dir != dir %u != %u\n", rm_dir, dir);
		goto out;
	}

	if (rm_dir == CALL) {
		if (rpc_call(data, offset, datalen, rpc_info) < 0)
			goto out;

		rpc_info->xid = xid;

		return ret;
	} else {
		/* Check XID */
		if (xid != rpc_info->xid) {
			pr_debug("RPC REPL: XID does not match: %u != %u\n",
				 xid, rpc_info->xid);
			goto out;
		}
		if (rpc_reply(data, offset, datalen, rpc_info, &port_ptr) < 0)
			goto out;

		port = IXDR_GET_INT32(port_ptr);
		port = htons(port);

		/* We refer to the reverse direction ("!dir") tuples here,
		 * because we're expecting something in the other direction.
		 * Doesn't matter unless NAT is happening.  */
		cthelper_get_addr_dst(myct->ct, !dir, &daddr);
		cthelper_get_addr_src(myct->ct, !dir, &addr);

		exp = nfexp_new();
		if (exp == NULL)
			goto out;

		if (cthelper_expect_init(exp, myct->ct, 0, &addr, &daddr,
					 rpc_info->pm_prot,
					 NULL, &port, NF_CT_EXPECT_PERMANENT)) {
			pr_debug("RPC: failed to init expectation\n");
			goto out_exp;
		}

		/* Now, NAT might want to mangle the packet, and register the
		 * (possibly changed) expectation itself. */
		if (nfct_get_attr_u32(myct->ct, ATTR_STATUS) & IPS_NAT_MASK) {
			ret = nf_nat_rpc(pkt, dir, exp, rpc_info->pm_prot,
					 port_ptr);
			goto out_exp;
		}

		/* Can't expect this?  Best to drop packet now. */
		if (cthelper_add_expect(exp) < 0) {
			pr_debug("RPC: cannot add expectation: %s\n",
				 strerror(errno));
			ret = NF_DROP;
		}
	}

out_exp:
	nfexp_destroy(exp);
out:
	rpc_info->xid = 0;
	return ret;
}
static PyObject*
serialize_connection(struct nf_conntrack *ct)
{
    PyObject *dict;
    uint8_t proto3, proto4;

    dict = PyDict_New();
    if (!dict)
        goto error;

    if (add_key(dict, "handle", PyLong_FromVoidPtr(ct)))
        goto error;

    proto3 = nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO);
    if (add_key(dict, "orig_l3proto", PyLong_FromUnsignedLong(proto3)))
        goto error;

    if (proto3 == AF_INET) {
        if (add_key(dict, "orig_ipv4_src", get_attr32(ct, ATTR_ORIG_IPV4_SRC, 1)))
            goto error;
        if (add_key(dict, "orig_ipv4_dst", get_attr32(ct, ATTR_ORIG_IPV4_DST, 1)))
            goto error;
#ifdef EXTRAFIELDS
        if (add_key(dict, "repl_ipv4_src", get_attr32(ct, ATTR_REPL_IPV4_SRC, 1)))
            goto error;
        if (add_key(dict, "repl_ipv4_dst", get_attr32(ct, ATTR_REPL_IPV4_DST, 1)))
            goto error;
#endif
    } else if (proto3 == AF_INET6) {
        if (add_key(dict, "orig_ipv6_src", get_attr128(ct, ATTR_ORIG_IPV6_SRC)))
            goto error;
        if (add_key(dict, "orig_ipv6_dst", get_attr128(ct, ATTR_ORIG_IPV6_DST)))
            goto error;
#ifdef EXTRAFIELDS
        if (add_key(dict, "repl_ipv6_src", get_attr128(ct, ATTR_REPL_IPV6_SRC)))
            goto error;
        if (add_key(dict, "repl_ipv6_dst", get_attr128(ct, ATTR_REPL_IPV6_DST)))
            goto error;
#endif
    }

    proto4 = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO);
    if (add_key(dict, "orig_l4proto", PyLong_FromUnsignedLong(proto4)))
        goto error;
    if (proto4 == IPPROTO_TCP || proto4 == IPPROTO_UDP) {
        if (add_key(dict, "orig_port_src", get_attr16(ct, ATTR_ORIG_PORT_SRC, 1)))
            goto error;
        if (add_key(dict, "orig_port_dst", get_attr16(ct, ATTR_ORIG_PORT_DST, 1)))
            goto error;
#ifdef EXTRAFIELDS
        if (add_key(dict, "repl_port_src", get_attr16(ct, ATTR_REPL_PORT_SRC, 1)))
            goto error;
        if (add_key(dict, "repl_port_dst", get_attr16(ct, ATTR_REPL_PORT_DST, 1)))
            goto error;
#endif
        if (proto4 == IPPROTO_TCP) {
            if (add_key(dict, "tcp_state", get_attr16(ct, ATTR_TCP_STATE, 1)))
                goto error;
#ifdef EXTRAFIELDS
            if (add_key(dict, "tcp_flags_orig", get_attr8(ct, ATTR_TCP_FLAGS_ORIG)))
                goto error;
            if (add_key(dict, "tcp_flags_repl", get_attr8(ct, ATTR_TCP_FLAGS_REPL)))
                goto error;
            if (add_key(dict, "tcp_mask_orig", get_attr8(ct, ATTR_TCP_MASK_ORIG)))
                goto error;
            if (add_key(dict, "tcp_mask_repl", get_attr8(ct, ATTR_TCP_MASK_REPL)))
                goto error;
#endif
        }
    } else if (proto4 == IPPROTO_ICMP || proto4 == IPPROTO_ICMPV6) {
        if (add_key(dict, "icmp_type", get_attr8(ct, ATTR_ICMP_TYPE)))
            goto error;
        if (add_key(dict, "icmp_code", get_attr8(ct, ATTR_ICMP_CODE)))
            goto error;
#ifdef EXTRAFIELDS
        if (add_key(dict, "icmp_id", get_attr16(ct, ATTR_ICMP_ID, 1)))
            goto error;
#endif
    }

    if (add_key(dict, "timeout", get_attr32(ct, ATTR_TIMEOUT, 0)))
        goto error;
    if (add_key(dict, "mark", get_attr32(ct, ATTR_MARK, 0)))
        goto error;

    if (add_key(dict, "orig_counter_packets", get_attr32(ct, ATTR_ORIG_COUNTER_PACKETS, 0)))
        goto error;
    if (add_key(dict, "repl_counter_packets", get_attr32(ct, ATTR_REPL_COUNTER_PACKETS, 0)))
        goto error;
    if (add_key(dict, "orig_counter_bytes", get_attr64(ct, ATTR_ORIG_COUNTER_BYTES)))
        goto error;
    if (add_key(dict, "repl_counter_bytes", get_attr64(ct, ATTR_REPL_COUNTER_BYTES)))
        goto error;

#ifdef EXTRAFIELDS
    if (add_key(dict, "use", get_attr32(ct, ATTR_USE, 1)))
        goto error;

    if (add_key(dict, "status", get_attr32(ct, ATTR_STATUS, 0)))
        goto error;
#endif

#if 0
    if (add_key(dict, "id", get_attr32(ct, ATTR_ID, 1)))
        goto error;
#endif

/*
 * TODO:
	ATTR_TCP_STATE
	ATTR_SNAT_IPV4
	ATTR_DNAT_IPV4
	ATTR_SNAT_PORT
	ATTR_DNAT_PORT

	ATTR_MASTER_IPV4_SRC
	ATTR_MASTER_IPV4_DST
	ATTR_MASTER_IPV6_SRC
	ATTR_MASTER_IPV6_DST
	ATTR_MASTER_PORT_SRC
	ATTR_MASTER_PORT_DST
	ATTR_MASTER_L3PROTO
	ATTR_MASTER_L4PROTO
	ATTR_SECMARK
	ATTR_ORIG_NAT_SEQ_CORRECTION_POS
	ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE
	ATTR_ORIG_NAT_SEQ_OFFSET_AFTER
	ATTR_REPL_NAT_SEQ_CORRECTION_POS
	ATTR_REPL_NAT_SEQ_OFFSET_BEFORE
	ATTR_REPL_NAT_SEQ_OFFSET_AFTER
 */

    return dict;

error:
    Py_XDECREF(dict);
    return NULL;
}