unsigned int
seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir)
{
	struct nf_conn_counter *acct;

	acct = nf_conn_acct_find(ct);
	if (!acct)
		return 0;

	return seq_printf(s, "packets=%llu bytes=%llu ",
			  (unsigned long long)atomic64_read(&acct[dir].packets),
			  (unsigned long long)atomic64_read(&acct[dir].bytes));
};
Exemple #2
0
static int total_acct_packets(struct nf_conn *ct)
{
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26)
	BUG_ON(ct == NULL);
	return (ct->counters[IP_CT_DIR_ORIGINAL].packets + ct->counters[IP_CT_DIR_REPLY].packets);
#else
	struct nf_conn_counter *acct;

	BUG_ON(ct == NULL);
	acct = nf_conn_acct_find(ct);
	if (!acct)
		return  0;
	return (acct[IP_CT_DIR_ORIGINAL].packets + acct[IP_CT_DIR_REPLY].packets);
#endif
}
Exemple #3
0
/* function to be called by hook */
static unsigned int 
hook_func(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in,
          const struct net_device *out, int (*okfn)(struct sk_buff *))
{
    struct nf_conn *ct;
	enum ip_conntrack_info ctinfo;
    struct nf_conn_counter *acct;

    if (!skb) {
        return NF_ACCEPT;
    }

    if (in == NULL) {
        return NF_ACCEPT;
    } else if (in->name == NULL) {
        return NF_ACCEPT;
    }
    
    if (memcmp(devname, "all", 3) != 0) {
        if (memcmp(devname, in->name, 4) != 0) {
            return NF_ACCEPT;
        }
    }

    /* conntrack check */
    if (skb->nfct == NULL) {
        /* if (net_ratelimit())
         *     pr_info("skb->nfct == NULL!\n"); */
        return NF_ACCEPT;
    }
    ct = nf_ct_get(skb, &ctinfo);

    acct = nf_conn_acct_find(ct);
    if (!acct) {
        if (net_ratelimit())
            pr_info("acct is NULL\n");
        return NF_ACCEPT;
    }

	if (ct->proto.tcp.state == TCP_CONNTRACK_CLOSE_WAIT) {
        pr_info("%pI4 --> %pI4: %llu bytes CLOSE_WAIT\n", &iph->saddr, &iph->daddr, 
            acct[IP_CT_DIR_ORIGINAL].bytes + acct[IP_CT_DIR_REPLY].bytes);
    }

    return NF_ACCEPT;
}
Exemple #4
0
static bool
connbytes_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
    const struct xt_connbytes_info *sinfo = par->matchinfo;
    const struct nf_conn *ct;
    enum ip_conntrack_info ctinfo;
    u_int64_t what = 0;	/* initialize to make gcc happy */
    u_int64_t bytes = 0;
    u_int64_t pkts = 0;
    const struct nf_conn_counter *counters;

    ct = nf_ct_get(skb, &ctinfo);
    if (!ct)
        return false;

    counters = nf_conn_acct_find(ct);
    if (!counters)
        return false;

    switch (sinfo->what) {
    case XT_CONNBYTES_PKTS:
        switch (sinfo->direction) {
        case XT_CONNBYTES_DIR_ORIGINAL:
            what = counters[IP_CT_DIR_ORIGINAL].packets;
            break;
        case XT_CONNBYTES_DIR_REPLY:
            what = counters[IP_CT_DIR_REPLY].packets;
            break;
        case XT_CONNBYTES_DIR_BOTH:
            what = counters[IP_CT_DIR_ORIGINAL].packets;
            what += counters[IP_CT_DIR_REPLY].packets;
            break;
        }
        break;
    case XT_CONNBYTES_BYTES:
        switch (sinfo->direction) {
        case XT_CONNBYTES_DIR_ORIGINAL:
            what = counters[IP_CT_DIR_ORIGINAL].bytes;
            break;
        case XT_CONNBYTES_DIR_REPLY:
            what = counters[IP_CT_DIR_REPLY].bytes;
            break;
        case XT_CONNBYTES_DIR_BOTH:
            what = counters[IP_CT_DIR_ORIGINAL].bytes;
            what += counters[IP_CT_DIR_REPLY].bytes;
            break;
        }
        break;
    case XT_CONNBYTES_AVGPKT:
        switch (sinfo->direction) {
        case XT_CONNBYTES_DIR_ORIGINAL:
            bytes = counters[IP_CT_DIR_ORIGINAL].bytes;
            pkts  = counters[IP_CT_DIR_ORIGINAL].packets;
            break;
        case XT_CONNBYTES_DIR_REPLY:
            bytes = counters[IP_CT_DIR_REPLY].bytes;
            pkts  = counters[IP_CT_DIR_REPLY].packets;
            break;
        case XT_CONNBYTES_DIR_BOTH:
            bytes = counters[IP_CT_DIR_ORIGINAL].bytes +
                    counters[IP_CT_DIR_REPLY].bytes;
            pkts  = counters[IP_CT_DIR_ORIGINAL].packets +
                    counters[IP_CT_DIR_REPLY].packets;
            break;
        }
        if (pkts != 0)
            what = div64_u64(bytes, pkts);
        break;
    }

    if (sinfo->count.to)
        return what <= sinfo->count.to && what >= sinfo->count.from;
    else
        return what >= sinfo->count.from;
}
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;
}
Exemple #6
0
/*
 * sfe_cm_sync_rule()
 *	Synchronize a connection's state.
 */
static void sfe_cm_sync_rule(struct sfe_ipv4_sync *sis)
{
	struct nf_conntrack_tuple_hash *h;
	struct nf_conntrack_tuple tuple;
	struct nf_conn *ct;
	struct nf_conn_counter *acct;

	/*
	 * Create a tuple so as to be able to look up a connection
	 */
	memset(&tuple, 0, sizeof(tuple));
	tuple.src.u3.ip = sis->src_ip;
	tuple.src.u.all = (__be16)sis->src_port;
	tuple.src.l3num = AF_INET;

	tuple.dst.u3.ip = sis->dest_ip;
	tuple.dst.dir = IP_CT_DIR_ORIGINAL;
	tuple.dst.protonum = (uint8_t)sis->protocol;
	tuple.dst.u.all = (__be16)sis->dest_port;

	DEBUG_TRACE("update connection - p: %d, s: %pI4:%u, d: %pI4:%u\n",
		    (int)tuple.dst.protonum,
		    &tuple.src.u3.ip, (unsigned int)ntohs(tuple.src.u.all),
		    &tuple.dst.u3.ip, (unsigned int)ntohs(tuple.dst.u.all));

	/*
	 * Look up conntrack connection
	 */
	h = nf_conntrack_find_get(&init_net, NF_CT_DEFAULT_ZONE, &tuple);
	if (unlikely(!h)) {
		DEBUG_TRACE("no connection found\n");
		return;
	}

	ct = nf_ct_tuplehash_to_ctrack(h);
	NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct);

	/*
	 * Only update if this is not a fixed timeout
	 */
	if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) {
		ct->timeout.expires += sis->delta_jiffies;
	}

	acct = nf_conn_acct_find(ct);
	if (acct) {
		spin_lock_bh(&ct->lock);
		atomic64_set(&acct[IP_CT_DIR_ORIGINAL].packets, sis->src_packet_count);
		atomic64_set(&acct[IP_CT_DIR_ORIGINAL].bytes, sis->src_byte_count);
		atomic64_set(&acct[IP_CT_DIR_REPLY].packets, sis->dest_packet_count);
		atomic64_set(&acct[IP_CT_DIR_REPLY].bytes, sis->dest_byte_count);
		spin_unlock_bh(&ct->lock);
	}

	switch (sis->protocol) {
	case IPPROTO_TCP:
		spin_lock_bh(&ct->lock);
		if (ct->proto.tcp.seen[0].td_maxwin < sis->src_td_max_window) {
			ct->proto.tcp.seen[0].td_maxwin = sis->src_td_max_window;
		}
		if ((int32_t)(ct->proto.tcp.seen[0].td_end - sis->src_td_end) < 0) {
			ct->proto.tcp.seen[0].td_end = sis->src_td_end;
		}
		if ((int32_t)(ct->proto.tcp.seen[0].td_maxend - sis->src_td_max_end) < 0) {
			ct->proto.tcp.seen[0].td_maxend = sis->src_td_max_end;
		}
		if (ct->proto.tcp.seen[1].td_maxwin < sis->dest_td_max_window) {
			ct->proto.tcp.seen[1].td_maxwin = sis->dest_td_max_window;
		}
		if ((int32_t)(ct->proto.tcp.seen[1].td_end - sis->dest_td_end) < 0) {
			ct->proto.tcp.seen[1].td_end = sis->dest_td_end;
		}
		if ((int32_t)(ct->proto.tcp.seen[1].td_maxend - sis->dest_td_max_end) < 0) {
			ct->proto.tcp.seen[1].td_maxend = sis->dest_td_max_end;
		}
		spin_unlock_bh(&ct->lock);
		break;
	}

	/*
	 * Release connection
	 */
	nf_ct_put(ct);
}