net/netfilter/nf_conntrack_timeout.c

Source file repositories/reference/linux-study-clean/net/netfilter/nf_conntrack_timeout.c

File Facts

System
Linux kernel
Corpus path
net/netfilter/nf_conntrack_timeout.c
Extension
.c
Size
4070 bytes
Lines
168
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!t) {
			rcu_read_unlock();
			return 0;
		}

		if (!timeout || t == timeout) {
			RCU_INIT_POINTER(timeout_ext->timeout, NULL);

			/* No race with nf_conntrack_free() which is called
			 * only after the conntrack has been removed from
			 * the hashes.
			 */
			if (refcount_dec_and_test(&t->refcnt))
				kfree_rcu(t, rcu);
		}
		rcu_read_unlock();
	}

	/* We are not intended to delete this conntrack. */
	return 0;
}

void nf_ct_untimeout(struct net *net, struct nf_ct_timeout *timeout)
{
	struct nf_ct_iter_data iter_data = {
		.net	= net,
		.data	= timeout,
	};

	nf_ct_iterate_cleanup_net(untimeout, &iter_data);
}
EXPORT_SYMBOL_GPL(nf_ct_untimeout);

static void __nf_ct_timeout_put(struct nf_ct_timeout *timeout)
{
	const struct nf_ct_timeout_hooks *h = rcu_dereference(nf_ct_timeout_hook);

	if (h)
		h->timeout_put(timeout);
}

int nf_ct_set_timeout(struct net *net, struct nf_conn *ct,
		      u8 l3num, u8 l4num, const char *timeout_name)
{
	const struct nf_ct_timeout_hooks *h;
	struct nf_ct_timeout *timeout;
	struct nf_conn_timeout *timeout_ext;
	const char *errmsg = NULL;
	int ret = 0;

	WARN_ON_ONCE(!nf_ct_is_template(ct));

	rcu_read_lock();
	h = rcu_dereference(nf_ct_timeout_hook);
	if (!h) {
		ret = -ENOENT;
		errmsg = "Timeout policy base is empty";
		goto out;
	}

	timeout = h->timeout_find_get(net, timeout_name);
	if (!timeout) {
		ret = -ENOENT;
		pr_info_ratelimited("No such timeout policy \"%s\"\n",
				    timeout_name);
		goto out;
	}

	if (timeout->l3num != l3num) {
		ret = -EINVAL;
		pr_info_ratelimited("Timeout policy `%s' can only be used by "
				    "L%d protocol number %d\n",
				    timeout_name, 3, timeout->l3num);
		goto err_put_timeout;
	}
	/* Make sure the timeout policy matches any existing protocol tracker,
	 * otherwise default to generic.
	 */
	if (timeout->l4proto->l4proto != l4num) {
		ret = -EINVAL;
		pr_info_ratelimited("Timeout policy `%s' can only be used by "
				    "L%d protocol number %d\n",
				    timeout_name, 4, timeout->l4proto->l4proto);
		goto err_put_timeout;
	}
	timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC);
	if (!timeout_ext) {
		ret = -ENOMEM;
		goto err_put_timeout;
	}

Annotation

Implementation Notes