<commit_before>/* Expectation handling for nf_conntrack. */

/* (C) 1999-2001 Paul `Rusty' Russell
 * (C) 2002-2006 Netfilter Core Team <<EMAIL>>
 * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/types.h>
#include <linux/netfilter.h>
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stddef.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/percpu.h>
#include <linux/kernel.h>

#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_tuple.h>

LIST_HEAD(nf_conntrack_expect_list);
EXPORT_SYMBOL_GPL(nf_conntrack_expect_list);

kmem_cache_t *nf_conntrack_expect_cachep __read_mostly;
static unsigned int nf_conntrack_expect_next_id;

/* nf_conntrack_expect helper functions */
void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
{
	struct nf_conn_help *master_help = nfct_help(exp->master);

	NF_CT_ASSERT(master_help);
	NF_CT_ASSERT(!timer_pending(&exp->timeout));

	list_del(&exp->list);
	NF_CT_STAT_INC(expect_delete);
	master_help->expecting--;
	nf_conntrack_expect_put(exp);
}
EXPORT_SYMBOL_GPL(nf_ct_unlink_expect);

static void expectation_timed_out(unsigned long ul_expect)
{
	struct nf_conntrack_expect *exp = (void *)ul_expect;

	write_lock_bh(&nf_conntrack_lock);
	nf_ct_unlink_expect(exp);
	write_unlock_bh(&nf_conntrack_lock);
	nf_conntrack_expect_put(exp);
}

struct nf_conntrack_expect *
__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
{
	struct nf_conntrack_expect *i;

	list_for_each_entry(i, &nf_conntrack_expect_list, list) {
		if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
			return i;
	}
	return NULL;
}
EXPORT_SYMBOL_GPL(__nf_conntrack_expect_find);

/* Just find a expectation corresponding to a tuple. */
struct nf_conntrack_expect *
nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple)
{
	struct nf_conntrack_expect *i;

	read_lock_bh(&nf_conntrack_lock);
	i = __nf_conntrack_expect_find(tuple);
	if (i)
		atomic_inc(&i->use);
	read_unlock_bh(&nf_conntrack_lock);

	return i;
}
EXPORT_SYMBOL_GPL(nf_conntrack_expect_find_get);

/* If an expectation for this connection is found, it gets delete from
 * global list then returned. */
struct nf_conntrack_expect *
find_expectation(const struct nf_conntrack_tuple *tuple)
{
	struct nf_conntrack_expect *i;

	list_for_each_entry(i, &nf_conntrack_expect_list, list) {
	/* If master is not in hash table yet (ie. packet hasn't left
	   this machine yet), how can other end know about expected?
	   Hence these are not the droids you are looking for (if
	   master ct never got confirmed, we'd hold a reference to it
	   and weird things would happen to future packets). */
		if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)
		    && nf_ct_is_confirmed(i->master)) {
			if (i->flags & NF_CT_EXPECT_PERMANENT) {
				atomic_inc(&i->use);
				return i;
			} else if (del_timer(&i->timeout)) {
				nf_ct_unlink_expect(i);
				return i;
			}
		}
	}
	return NULL;
}

/* delete all expectations for this conntrack */
void nf_ct_remove_expectations(struct nf_conn *ct)
{
	struct nf_conntrack_expect *i, *tmp;
	struct nf_conn_help *help = nfct_help(ct);

	/* Optimization: most connection never expect any others. */
	if (!help || help->expecting == 0)
		return;

	list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) {
		if (i->master == ct && del_timer(&i->timeout)) {
			nf_ct_unlink_expect(i);
			nf_conntrack_expect_put(i);
 		}
	}
}
EXPORT_SYMBOL_GPL(nf_ct_remove_expectations);

/* Would two expected things clash? */
static inline int expect_clash(const struct nf_conntrack_expect *a,<commit_msg>[NETFILTER]: nf_conntrack: Don't try to find clashed expectation<commit_after>/* Expectation handling for nf_conntrack. */

/* (C) 1999-2001 Paul `Rusty' Russell
 * (C) 2002-2006 Netfilter Core Team <<EMAIL>>
 * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/types.h>
#include <linux/netfilter.h>
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stddef.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/percpu.h>
#include <linux/kernel.h>

#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_tuple.h>

LIST_HEAD(nf_conntrack_expect_list);
EXPORT_SYMBOL_GPL(nf_conntrack_expect_list);

kmem_cache_t *nf_conntrack_expect_cachep __read_mostly;
static unsigned int nf_conntrack_expect_next_id;

/* nf_conntrack_expect helper functions */
void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
{
	struct nf_conn_help *master_help = nfct_help(exp->master);

	NF_CT_ASSERT(master_help);
	NF_CT_ASSERT(!timer_pending(&exp->timeout));

	list_del(&exp->list);
	NF_CT_STAT_INC(expect_delete);
	master_help->expecting--;
	nf_conntrack_expect_put(exp);
}
EXPORT_SYMBOL_GPL(nf_ct_unlink_expect);

static void expectation_timed_out(unsigned long ul_expect)
{
	struct nf_conntrack_expect *exp = (void *)ul_expect;

	write_lock_bh(&nf_conntrack_lock);
	nf_ct_unlink_expect(exp);
	write_unlock_bh(&nf_conntrack_lock);
	nf_conntrack_expect_put(exp);
}

struct nf_conntrack_expect *
__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
{
	struct nf_conntrack_expect *i;

	list_for_each_entry(i, &nf_conntrack_expect_list, list) {
		if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
			return i;
	}
	return NULL;
}
EXPORT_SYMBOL_GPL(__nf_conntrack_expect_find);

/* Just find a expectation corresponding to a tuple. */
struct nf_conntrack_expect *
nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple)
{
	struct nf_conntrack_expect *i;

	read_lock_bh(&nf_conntrack_lock);
	i = __nf_conntrack_expect_find(tuple);
	if (i)
		atomic_inc(&i->use);
	read_unlock_bh(&nf_conntrack_lock);

	return i;
}
EXPORT_SYMBOL_GPL(nf_conntrack_expect_find_get);

/* If an expectation for this connection is found, it gets delete from
 * global list then returned. */
struct nf_conntrack_expect *
find_expectation(const struct nf_conntrack_tuple *tuple)
{
	struct nf_conntrack_expect *exp;

	exp = __nf_conntrack_expect_find(tuple);
	if (!exp)
		return NULL;

	/* If master is not in hash table yet (ie. packet hasn't left
	   this machine yet), how can other end know about expected?
	   Hence these are not the droids you are looking for (if
	   master ct never got confirmed, we'd hold a reference to it
	   and weird things would happen to future packets). */
	if (!nf_ct_is_confirmed(exp->master))
		return NULL;

	if (exp->flags & NF_CT_EXPECT_PERMANENT) {
		atomic_inc(&exp->use);
		return exp;
	} else if (del_timer(&exp->timeout)) {
		nf_ct_unlink_expect(exp);
		return exp;
	}

	return NULL;
}

/* delete all expectations for this conntrack */
void nf_ct_remove_expectations(struct nf_conn *ct)
{
	struct nf_conntrack_expect *i, *tmp;
	struct nf_conn_help *help = nfct_help(ct);

	/* Optimization: most connection never expect any others. */
	if (!help || help->expecting == 0)
		return;

	list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) {
		if (i->master == ct && del_timer(&i->timeout)) {
			nf_ct_unlink_expect(i);
			nf_conntrack_expect_put(i);
 		}
	}
}
EXPORT_SYMBOL_GPL(nf_ct_remove_expectations);

/* Would two expected things clash? */
static inline int expect_clash(const struct nf_conntrack_expect *a,
{'fraction_non_alphanumeric': 0.10825065929925907, 'fraction_numerical': 0.006781363807610197, 'mean_word_length': 5.65886287625418, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4651141', 'n_tokens_mistral': 3036, 'n_tokens_neox': 2884, 'n_words': 652}