Exemple #1
0
static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key,
			     const struct ovs_key_ct_labels *labels,
			     const struct ovs_key_ct_labels *mask)
{
	enum ip_conntrack_info ctinfo;
	struct nf_conn_labels *cl;
	struct nf_conn *ct;
	int err;

	/* The connection could be invalid, in which case set_label is no-op.*/
	ct = nf_ct_get(skb, &ctinfo);
	if (!ct)
		return 0;

	cl = nf_ct_labels_find(ct);
	if (!cl) {
		nf_ct_labels_ext_add(ct);
		cl = nf_ct_labels_find(ct);
	}
	if (!cl || cl->words * sizeof(long) < OVS_CT_LABELS_LEN)
		return -ENOSPC;

	err = nf_connlabels_replace(ct, (u32 *)labels, (u32 *)mask,
				    OVS_CT_LABELS_LEN / sizeof(u32));
	if (err)
		return err;

	ovs_ct_get_labels(ct, &key->ct.labels);
	return 0;
}
bool nf_connlabel_match(const struct nf_conn *ct, u16 bit)
{
	struct nf_conn_labels *labels = nf_ct_labels_find(ct);

	if (!labels)
		return false;

	return bit < label_bits(labels) && test_bit(bit, labels->bits);
}
int nf_connlabel_set(struct nf_conn *ct, u16 bit)
{
	struct nf_conn_labels *labels = nf_ct_labels_find(ct);

	if (!labels || bit >= label_bits(labels))
		return -ENOSPC;

	if (test_bit(bit, labels->bits))
		return 0;

	if (test_and_set_bit(bit, labels->bits))
		nf_conntrack_event_cache(IPCT_LABEL, ct);

	return 0;
}
Exemple #4
0
static void ovs_ct_get_labels(const struct nf_conn *ct,
			      struct ovs_key_ct_labels *labels)
{
	struct nf_conn_labels *cl = ct ? nf_ct_labels_find(ct) : NULL;

	if (cl) {
		size_t len = cl->words * sizeof(long);

		if (len > OVS_CT_LABELS_LEN)
			len = OVS_CT_LABELS_LEN;
		else if (len < OVS_CT_LABELS_LEN)
			memset(labels, 0, OVS_CT_LABELS_LEN);
		memcpy(labels, cl->bits, len);
	} else {
		memset(labels, 0, OVS_CT_LABELS_LEN);
	}
}
static void nft_ct_get_eval(const struct nft_expr *expr,
                            struct nft_regs *regs,
                            const struct nft_pktinfo *pkt)
{
    const struct nft_ct *priv = nft_expr_priv(expr);
    u32 *dest = &regs->data[priv->dreg];
    enum ip_conntrack_info ctinfo;
    const struct nf_conn *ct;
    const struct nf_conn_help *help;
    const struct nf_conntrack_tuple *tuple;
    const struct nf_conntrack_helper *helper;
    unsigned int state;

    ct = nf_ct_get(pkt->skb, &ctinfo);

    switch (priv->key) {
    case NFT_CT_STATE:
        if (ct == NULL)
            state = NF_CT_STATE_INVALID_BIT;
        else if (nf_ct_is_untracked(ct))
            state = NF_CT_STATE_UNTRACKED_BIT;
        else
            state = NF_CT_STATE_BIT(ctinfo);
        *dest = state;
        return;
    default:
        break;
    }

    if (ct == NULL)
        goto err;

    switch (priv->key) {
    case NFT_CT_DIRECTION:
        *dest = CTINFO2DIR(ctinfo);
        return;
    case NFT_CT_STATUS:
        *dest = ct->status;
        return;
#ifdef CONFIG_NF_CONNTRACK_MARK
    case NFT_CT_MARK:
        *dest = ct->mark;
        return;
#endif
#ifdef CONFIG_NF_CONNTRACK_SECMARK
    case NFT_CT_SECMARK:
        *dest = ct->secmark;
        return;
#endif
    case NFT_CT_EXPIRATION:
        *dest = jiffies_to_msecs(nf_ct_expires(ct));
        return;
    case NFT_CT_HELPER:
        if (ct->master == NULL)
            goto err;
        help = nfct_help(ct->master);
        if (help == NULL)
            goto err;
        helper = rcu_dereference(help->helper);
        if (helper == NULL)
            goto err;
        strncpy((char *)dest, helper->name, NF_CT_HELPER_NAME_LEN);
        return;
#ifdef CONFIG_NF_CONNTRACK_LABELS
    case NFT_CT_LABELS: {
        struct nf_conn_labels *labels = nf_ct_labels_find(ct);
        unsigned int size;

        if (!labels) {
            memset(dest, 0, NF_CT_LABELS_MAX_SIZE);
            return;
        }

        size = labels->words * sizeof(long);
        memcpy(dest, labels->bits, size);
        if (size < NF_CT_LABELS_MAX_SIZE)
            memset(((char *) dest) + size, 0,
                   NF_CT_LABELS_MAX_SIZE - size);
        return;
    }
#endif
    case NFT_CT_BYTES: /* fallthrough */
    case NFT_CT_PKTS: {
        const struct nf_conn_acct *acct = nf_conn_acct_find(ct);
        u64 count = 0;

        if (acct)
            count = nft_ct_get_eval_counter(acct->counter,
                                            priv->key, priv->dir);
        memcpy(dest, &count, sizeof(count));
        return;
    }
    default:
        break;
    }

    tuple = &ct->tuplehash[priv->dir].tuple;
    switch (priv->key) {
    case NFT_CT_L3PROTOCOL:
        *dest = nf_ct_l3num(ct);
        return;
    case NFT_CT_SRC:
        memcpy(dest, tuple->src.u3.all,
               nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
        return;
    case NFT_CT_DST:
        memcpy(dest, tuple->dst.u3.all,
               nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
        return;
    case NFT_CT_PROTOCOL:
        *dest = nf_ct_protonum(ct);
        return;
    case NFT_CT_PROTO_SRC:
        *dest = (__force __u16)tuple->src.u.all;
        return;
    case NFT_CT_PROTO_DST:
        *dest = (__force __u16)tuple->dst.u.all;
        return;
    default:
        break;
    }
    return;
err:
    regs->verdict.code = NFT_BREAK;
}