net/netfilter/nf_conntrack_proto_gre.c

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

File Facts

System
Linux kernel
Corpus path
net/netfilter/nf_conntrack_proto_gre.c
Extension
.c
Size
12772 bytes
Lines
455
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 (gre_key_cmpfn(km, t)) {
			key = km->tuple.src.u.gre.key;
			break;
		}
	}

	pr_debug("lookup src key 0x%x for ", key);
	nf_ct_dump_tuple(t);

	return key;
}

enum nf_ct_gre_km_act {
	NF_CT_GRE_KM_NEW,
	NF_CT_GRE_KM_BAD,
	NF_CT_GRE_KM_DUP
};

static enum nf_ct_gre_km_act
nf_ct_gre_km_acceptable(const struct nf_ct_pptp_master *ct_pptp_info,
			const struct nf_conntrack_tuple *orig,
			const struct nf_conntrack_tuple *repl)
{
	struct nf_ct_gre_keymap *km_orig, *km_repl;

	lockdep_assert_held(&keymap_lock);

	km_orig = ct_pptp_info->keymap[IP_CT_DIR_ORIGINAL];
	km_repl = ct_pptp_info->keymap[IP_CT_DIR_REPLY];

	if (km_orig && km_repl) {
		if (!gre_key_cmpfn(km_orig, orig))
			return NF_CT_GRE_KM_BAD;

		if (!gre_key_cmpfn(km_repl, repl))
			return NF_CT_GRE_KM_BAD;

		return NF_CT_GRE_KM_DUP;
	}

	DEBUG_NET_WARN_ON_ONCE(km_orig);
	DEBUG_NET_WARN_ON_ONCE(km_repl);
	return NF_CT_GRE_KM_NEW;
}

/* add keymap entries, associate with specified master ct */
bool nf_ct_gre_keymap_add(struct nf_conn *ct,
			  const struct nf_conntrack_tuple *orig,
			  const struct nf_conntrack_tuple *repl)
{
	struct net *net = nf_ct_net(ct);
	struct nf_gre_net *net_gre = gre_pernet(net);
	struct nf_ct_pptp_master *ct_pptp_info = nfct_help_data(ct);
	struct nf_ct_gre_keymap *km_orig, *km_repl;
	bool ret = false;

	if (!ct_pptp_info)
		return false;

	km_orig = kmalloc_obj(*km_orig, GFP_ATOMIC);
	if (!km_orig)
		return false;
	km_repl = kmalloc_obj(*km_repl, GFP_ATOMIC);
	if (!km_repl)
		goto km_free;

	memcpy(&km_orig->tuple, orig, sizeof(*orig));
	memcpy(&km_repl->tuple, repl, sizeof(*repl));

	spin_lock_bh(&keymap_lock);
	if (nf_ct_is_dying(ct))
		goto unlock_free;

	switch (nf_ct_gre_km_acceptable(ct_pptp_info, orig, repl)) {
	case NF_CT_GRE_KM_NEW:
		break;
	case NF_CT_GRE_KM_DUP:
		ret = true;
		goto unlock_free;
	case NF_CT_GRE_KM_BAD:
		pr_debug("trying to override keymap for ct %p\n", ct);
		goto unlock_free;
	}

	if (ct_pptp_info->keymap[IP_CT_DIR_ORIGINAL] ||
	    ct_pptp_info->keymap[IP_CT_DIR_REPLY])
		goto unlock_free;

	pr_debug("adding new entries %p,%p: ", km_orig, km_repl);
	nf_ct_dump_tuple(&km_orig->tuple);

Annotation

Implementation Notes