netfilter: nf_conntrack_pptp: move GRE specific cleanup to GRE tracker

Move the GRE specific cleanup to nf_conntrack_proto_gre.c to ensure that
the .destroy callback for the pptp helper is still reachable by existing
conntrack entries while pptp module is being removed.

This is a preparation patch, no functional changes are intended.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Pablo Neira Ayuso 2026-06-04 08:21:10 +02:00
parent 6031487d4e
commit fe97fd540a
3 changed files with 67 additions and 61 deletions

View File

@ -20,4 +20,8 @@ extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp;
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_gre;
#endif
#if IS_ENABLED(CONFIG_NF_CONNTRACK_PPTP)
void gre_pptp_destroy_siblings(struct nf_conn *ct);
#endif
#endif /*_NF_CONNTRACK_IPV4_H*/

View File

@ -124,65 +124,6 @@ static void pptp_expectfn(struct nf_conn *ct,
}
}
static int destroy_sibling_or_exp(struct net *net, struct nf_conn *ct,
const struct nf_conntrack_tuple *t)
{
const struct nf_conntrack_tuple_hash *h;
const struct nf_conntrack_zone *zone;
struct nf_conntrack_expect *exp;
struct nf_conn *sibling;
pr_debug("trying to timeout ct or exp for tuple ");
nf_ct_dump_tuple(t);
zone = nf_ct_zone(ct);
h = nf_conntrack_find_get(net, zone, t);
if (h) {
sibling = nf_ct_tuplehash_to_ctrack(h);
pr_debug("setting timeout of conntrack %p to 0\n", sibling);
sibling->proto.gre.timeout = 0;
sibling->proto.gre.stream_timeout = 0;
nf_ct_kill(sibling);
nf_ct_put(sibling);
return 1;
} else {
exp = nf_ct_expect_find_get(net, zone, t);
if (exp) {
pr_debug("unexpect_related of expect %p\n", exp);
nf_ct_unexpect_related(exp);
nf_ct_expect_put(exp);
return 1;
}
}
return 0;
}
/* timeout GRE data connections */
static void pptp_destroy_siblings(struct nf_conn *ct)
{
struct net *net = nf_ct_net(ct);
const struct nf_ct_pptp_master *ct_pptp_info = nfct_help_data(ct);
struct nf_conntrack_tuple t;
nf_ct_gre_keymap_destroy(ct);
/* try original (pns->pac) tuple */
memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t));
t.dst.protonum = IPPROTO_GRE;
t.src.u.gre.key = ct_pptp_info->pns_call_id;
t.dst.u.gre.key = ct_pptp_info->pac_call_id;
if (!destroy_sibling_or_exp(net, ct, &t))
pr_debug("failed to timeout original pns->pac ct/exp\n");
/* try reply (pac->pns) tuple */
memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t));
t.dst.protonum = IPPROTO_GRE;
t.src.u.gre.key = ct_pptp_info->pac_call_id;
t.dst.u.gre.key = ct_pptp_info->pns_call_id;
if (!destroy_sibling_or_exp(net, ct, &t))
pr_debug("failed to timeout reply pac->pns ct/exp\n");
}
/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)
{
@ -343,7 +284,7 @@ pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff,
info->cstate = PPTP_CALL_NONE;
/* untrack this call id, unexpect GRE packets */
pptp_destroy_siblings(ct);
gre_pptp_destroy_siblings(ct);
break;
case PPTP_WAN_ERROR_NOTIFY:
@ -593,7 +534,7 @@ static int __init nf_conntrack_pptp_init(void)
"pptp", PPTP_CONTROL_PORT, PPTP_CONTROL_PORT, PPTP_CONTROL_PORT,
&pptp_exp_policy, 0, conntrack_pptp_help, NULL, THIS_MODULE);
pptp.destroy = pptp_destroy_siblings;
pptp.destroy = gre_pptp_destroy_siblings;
return nf_conntrack_helper_register(&pptp, &pptp_ptr);
}

View File

@ -349,6 +349,67 @@ gre_timeout_nla_policy[CTA_TIMEOUT_GRE_MAX+1] = {
};
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
#if IS_ENABLED(CONFIG_NF_CONNTRACK_PPTP)
static int destroy_sibling_or_exp(struct net *net, struct nf_conn *ct,
const struct nf_conntrack_tuple *t)
{
const struct nf_conntrack_tuple_hash *h;
const struct nf_conntrack_zone *zone;
struct nf_conntrack_expect *exp;
struct nf_conn *sibling;
pr_debug("trying to timeout ct or exp for tuple ");
nf_ct_dump_tuple(t);
zone = nf_ct_zone(ct);
h = nf_conntrack_find_get(net, zone, t);
if (h) {
sibling = nf_ct_tuplehash_to_ctrack(h);
pr_debug("setting timeout of conntrack %p to 0\n", sibling);
sibling->proto.gre.timeout = 0;
sibling->proto.gre.stream_timeout = 0;
nf_ct_kill(sibling);
nf_ct_put(sibling);
return 1;
} else {
exp = nf_ct_expect_find_get(net, zone, t);
if (exp) {
pr_debug("unexpect_related of expect %p\n", exp);
nf_ct_unexpect_related(exp);
nf_ct_expect_put(exp);
return 1;
}
}
return 0;
}
void gre_pptp_destroy_siblings(struct nf_conn *ct)
{
struct net *net = nf_ct_net(ct);
const struct nf_ct_pptp_master *ct_pptp_info = nfct_help_data(ct);
struct nf_conntrack_tuple t;
nf_ct_gre_keymap_destroy(ct);
/* try original (pns->pac) tuple */
memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t));
t.dst.protonum = IPPROTO_GRE;
t.src.u.gre.key = ct_pptp_info->pns_call_id;
t.dst.u.gre.key = ct_pptp_info->pac_call_id;
if (!destroy_sibling_or_exp(net, ct, &t))
pr_debug("failed to timeout original pns->pac ct/exp\n");
/* try reply (pac->pns) tuple */
memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t));
t.dst.protonum = IPPROTO_GRE;
t.src.u.gre.key = ct_pptp_info->pac_call_id;
t.dst.u.gre.key = ct_pptp_info->pns_call_id;
if (!destroy_sibling_or_exp(net, ct, &t))
pr_debug("failed to timeout reply pac->pns ct/exp\n");
}
EXPORT_SYMBOL_GPL(gre_pptp_destroy_siblings);
#endif
void nf_conntrack_gre_init_net(struct net *net)
{
struct nf_gre_net *net_gre = gre_pernet(net);