* [PATCH nf-next 1/5] netfilter: nf_conntrack_helper: do not hash by tuple
2026-05-22 5:01 [PATCH nf-next 0/5] netfilter: conntrack: remove some code Florian Westphal
@ 2026-05-22 5:01 ` Florian Westphal
2026-05-22 5:01 ` [PATCH nf-next 2/5] netfilter: conntrack: get rid of tuple in helper definitions Florian Westphal
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2026-05-22 5:01 UTC (permalink / raw)
To: netfilter-devel; +Cc: Florian Westphal
Long time ago helpers were auto-assigned to connections based on
port/protocol match. For this reason, nf_conntrack_helper still contains
a full tuple.
Nowadays the only relevant entries in the tuple are the l3 and l4 protocol
numbers.
Prepare for tuple removal and switch to hashing name and l4 protocol.
l3num cannot be used because helpers can also register for "unspec"
protocol.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
net/netfilter/nf_conntrack_helper.c | 65 ++++++++++++-----------------
1 file changed, 27 insertions(+), 38 deletions(-)
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index b594cd244fe1..32f64f600417 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -40,32 +40,34 @@ static unsigned int nf_ct_helper_count __read_mostly;
static DEFINE_MUTEX(nf_ct_nat_helpers_mutex);
static struct list_head nf_ct_nat_helpers __read_mostly;
-/* Stupid hash, but collision free for the default registrations of the
- * helpers currently in the kernel. */
-static unsigned int helper_hash(const struct nf_conntrack_tuple *tuple)
+static unsigned int helper_hash(const char *name, u8 protonum)
{
- return (((tuple->src.l3num << 8) | tuple->dst.protonum) ^
- (__force __u16)tuple->src.u.all) % nf_ct_helper_hsize;
+ static u32 seed;
+ u32 initval;
+
+ get_random_once(&seed, sizeof(seed));
+
+ initval = seed ^ protonum;
+
+ return jhash(name, strlen(name), initval) % nf_ct_helper_hsize;
}
struct nf_conntrack_helper *
__nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum)
{
+ unsigned int i = helper_hash(name, protonum);
struct nf_conntrack_helper *h;
- unsigned int i;
- for (i = 0; i < nf_ct_helper_hsize; i++) {
- hlist_for_each_entry_rcu(h, &nf_ct_helper_hash[i], hnode) {
- if (strcmp(h->name, name))
- continue;
+ hlist_for_each_entry_rcu(h, &nf_ct_helper_hash[i], hnode) {
+ if (strcmp(h->name, name))
+ continue;
- if (h->tuple.src.l3num != NFPROTO_UNSPEC &&
- h->tuple.src.l3num != l3num)
- continue;
+ if (h->tuple.src.l3num != NFPROTO_UNSPEC &&
+ h->tuple.src.l3num != l3num)
+ continue;
- if (h->tuple.dst.protonum == protonum)
- return h;
- }
+ if (h->tuple.dst.protonum == protonum)
+ return h;
}
return NULL;
}
@@ -346,10 +348,9 @@ EXPORT_SYMBOL_GPL(nf_ct_helper_log);
int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
{
- struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) };
- unsigned int h = helper_hash(&me->tuple);
+ unsigned int h = helper_hash(me->name, me->tuple.dst.protonum);
struct nf_conntrack_helper *cur;
- int ret = 0, i;
+ int ret = 0;
BUG_ON(me->expect_policy == NULL);
BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES);
@@ -362,28 +363,16 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
return -EINVAL;
mutex_lock(&nf_ct_helper_mutex);
- for (i = 0; i < nf_ct_helper_hsize; i++) {
- hlist_for_each_entry(cur, &nf_ct_helper_hash[i], hnode) {
- if (!strcmp(cur->name, me->name) &&
- (cur->tuple.src.l3num == NFPROTO_UNSPEC ||
- cur->tuple.src.l3num == me->tuple.src.l3num) &&
- cur->tuple.dst.protonum == me->tuple.dst.protonum) {
- ret = -EBUSY;
- goto out;
- }
+ hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) {
+ if (!strcmp(cur->name, me->name) &&
+ (cur->tuple.src.l3num == NFPROTO_UNSPEC ||
+ cur->tuple.src.l3num == me->tuple.src.l3num) &&
+ cur->tuple.dst.protonum == me->tuple.dst.protonum) {
+ ret = -EBUSY;
+ goto out;
}
}
- /* avoid unpredictable behaviour for auto_assign_helper */
- if (!(me->flags & NF_CT_HELPER_F_USERSPACE)) {
- hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) {
- if (nf_ct_tuple_src_mask_cmp(&cur->tuple, &me->tuple,
- &mask)) {
- ret = -EBUSY;
- goto out;
- }
- }
- }
refcount_set(&me->refcnt, 1);
hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]);
nf_ct_helper_count++;
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH nf-next 2/5] netfilter: conntrack: get rid of tuple in helper definitions
2026-05-22 5:01 [PATCH nf-next 0/5] netfilter: conntrack: remove some code Florian Westphal
2026-05-22 5:01 ` [PATCH nf-next 1/5] netfilter: nf_conntrack_helper: do not hash by tuple Florian Westphal
@ 2026-05-22 5:01 ` Florian Westphal
2026-05-22 5:01 ` [PATCH nf-next 3/5] netfilter: nf_conntrack: switch to static registration Florian Westphal
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2026-05-22 5:01 UTC (permalink / raw)
To: netfilter-devel; +Cc: Florian Westphal
Leftover from the days when the kernel did automatic assignment of helpers
based on a pre-registered / well-known-port.
This helper autoassign was removed from the kernel, so all we really
need are the l3 and l4 protocol numbers.
Because helpers can register for UNSPEC (== l3 agnostic), we can also
remove redundant ipv4+ipv6 register requests.
In the broadcast helper, the only remaining consumer of the port number is
removed. AFAICS its not needed either: The expectation is populated from
the control connection reply tuple, so the src port is the original
directions destination (snmp for example).
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/net/netfilter/nf_conntrack_helper.h | 4 +-
net/ipv4/netfilter/nf_nat_snmp_basic_main.c | 5 +-
net/netfilter/nf_conntrack_amanda.c | 35 +++------
net/netfilter/nf_conntrack_broadcast.c | 2 -
net/netfilter/nf_conntrack_h323_main.c | 85 +++++++--------------
net/netfilter/nf_conntrack_helper.c | 20 ++---
net/netfilter/nf_conntrack_netbios_ns.c | 7 +-
net/netfilter/nf_conntrack_pptp.c | 5 +-
net/netfilter/nf_conntrack_snmp.c | 7 +-
net/netfilter/nfnetlink_cthelper.c | 20 ++---
10 files changed, 68 insertions(+), 122 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index de2f956abf34..ab41ff60e9d1 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -37,8 +37,8 @@ struct nf_conntrack_helper {
struct module *me; /* pointer to self */
const struct nf_conntrack_expect_policy *expect_policy;
- /* Tuple of things we will help (compared against server response) */
- struct nf_conntrack_tuple tuple;
+ u8 nfproto; /* l3num protocol that the helper supports (can be NFPROTO_UNSPEC) */
+ u8 l4proto; /* l4 protocol that the helper supports (UDP, TCP) */
/* Function to call when data passes; return verdict, or -1 to
invalidate. */
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic_main.c b/net/ipv4/netfilter/nf_nat_snmp_basic_main.c
index 717b726504fe..2ef2ea0736e9 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic_main.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic_main.c
@@ -207,9 +207,8 @@ static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
.help = help,
.expect_policy = &snmp_exp_policy,
.name = "snmp_trap",
- .tuple.src.l3num = AF_INET,
- .tuple.src.u.udp.port = cpu_to_be16(SNMP_TRAP_PORT),
- .tuple.dst.protonum = IPPROTO_UDP,
+ .nfproto = NFPROTO_IPV4,
+ .l4proto = IPPROTO_UDP,
};
static int __init nf_nat_snmp_basic_init(void)
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c
index d2c09e8dd872..6e9cf06991b3 100644
--- a/net/netfilter/nf_conntrack_amanda.c
+++ b/net/netfilter/nf_conntrack_amanda.c
@@ -169,35 +169,21 @@ static const struct nf_conntrack_expect_policy amanda_exp_policy = {
.timeout = 180,
};
-static struct nf_conntrack_helper amanda_helper[2] __read_mostly = {
- {
- .name = HELPER_NAME,
- .me = THIS_MODULE,
- .help = amanda_help,
- .tuple.src.l3num = AF_INET,
- .tuple.src.u.udp.port = cpu_to_be16(10080),
- .tuple.dst.protonum = IPPROTO_UDP,
- .expect_policy = &amanda_exp_policy,
- .nat_mod_name = NF_NAT_HELPER_NAME(HELPER_NAME),
- },
- {
- .name = "amanda",
- .me = THIS_MODULE,
- .help = amanda_help,
- .tuple.src.l3num = AF_INET6,
- .tuple.src.u.udp.port = cpu_to_be16(10080),
- .tuple.dst.protonum = IPPROTO_UDP,
- .expect_policy = &amanda_exp_policy,
- .nat_mod_name = NF_NAT_HELPER_NAME(HELPER_NAME),
- },
+static struct nf_conntrack_helper amanda_helper __read_mostly = {
+ .name = HELPER_NAME,
+ .me = THIS_MODULE,
+ .help = amanda_help,
+ .nfproto = NFPROTO_UNSPEC,
+ .l4proto = IPPROTO_UDP,
+ .expect_policy = &amanda_exp_policy,
+ .nat_mod_name = NF_NAT_HELPER_NAME(HELPER_NAME),
};
static void __exit nf_conntrack_amanda_fini(void)
{
int i;
- nf_conntrack_helpers_unregister(amanda_helper,
- ARRAY_SIZE(amanda_helper));
+ nf_conntrack_helper_unregister(&amanda_helper);
for (i = 0; i < ARRAY_SIZE(search); i++)
textsearch_destroy(search[i].ts);
}
@@ -217,8 +203,7 @@ static int __init nf_conntrack_amanda_init(void)
goto err1;
}
}
- ret = nf_conntrack_helpers_register(amanda_helper,
- ARRAY_SIZE(amanda_helper));
+ ret = nf_conntrack_helper_register(&amanda_helper);
if (ret < 0)
goto err1;
return 0;
diff --git a/net/netfilter/nf_conntrack_broadcast.c b/net/netfilter/nf_conntrack_broadcast.c
index 75e53fde6b29..3113ed150755 100644
--- a/net/netfilter/nf_conntrack_broadcast.c
+++ b/net/netfilter/nf_conntrack_broadcast.c
@@ -62,8 +62,6 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb,
exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
helper = rcu_dereference(help->helper);
- if (helper)
- exp->tuple.src.u.udp.port = helper->tuple.src.u.udp.port;
exp->mask.src.u3.ip = mask;
exp->mask.src.u.udp.port = htons(0xFFFF);
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index b2fe6554b9cf..3c66d81f5ab0 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -59,8 +59,8 @@ static DEFINE_SPINLOCK(nf_h323_lock);
static char *h323_buffer;
static struct nf_conntrack_helper nf_conntrack_helper_h245;
-static struct nf_conntrack_helper nf_conntrack_helper_q931[];
-static struct nf_conntrack_helper nf_conntrack_helper_ras[];
+static struct nf_conntrack_helper nf_conntrack_helper_q931;
+static struct nf_conntrack_helper nf_conntrack_helper_ras;
static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
struct nf_conn *ct, enum ip_conntrack_info ctinfo,
@@ -580,8 +580,8 @@ static const struct nf_conntrack_expect_policy h245_exp_policy = {
static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = {
.name = "H.245",
.me = THIS_MODULE,
- .tuple.src.l3num = AF_UNSPEC,
- .tuple.dst.protonum = IPPROTO_UDP,
+ .nfproto = NFPROTO_UNSPEC,
+ .l4proto = IPPROTO_UDP,
.help = h245_help,
.expect_policy = &h245_exp_policy,
};
@@ -767,7 +767,7 @@ static int expect_callforwarding(struct sk_buff *skb,
nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
&ct->tuplehash[!dir].tuple.src.u3, &addr,
IPPROTO_TCP, NULL, &port);
- rcu_assign_pointer(exp->assign_helper, nf_conntrack_helper_q931);
+ rcu_assign_pointer(exp->assign_helper, &nf_conntrack_helper_q931);
nathook = rcu_dereference(nfct_h323_nat_hook);
if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
@@ -1140,25 +1140,13 @@ static const struct nf_conntrack_expect_policy q931_exp_policy = {
.timeout = 240,
};
-static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
- {
- .name = "Q.931",
- .me = THIS_MODULE,
- .tuple.src.l3num = AF_INET,
- .tuple.src.u.tcp.port = cpu_to_be16(Q931_PORT),
- .tuple.dst.protonum = IPPROTO_TCP,
- .help = q931_help,
- .expect_policy = &q931_exp_policy,
- },
- {
- .name = "Q.931",
- .me = THIS_MODULE,
- .tuple.src.l3num = AF_INET6,
- .tuple.src.u.tcp.port = cpu_to_be16(Q931_PORT),
- .tuple.dst.protonum = IPPROTO_TCP,
- .help = q931_help,
- .expect_policy = &q931_exp_policy,
- },
+static struct nf_conntrack_helper nf_conntrack_helper_q931 __read_mostly = {
+ .name = "Q.931",
+ .me = THIS_MODULE,
+ .nfproto = NFPROTO_UNSPEC,
+ .l4proto = IPPROTO_TCP,
+ .help = q931_help,
+ .expect_policy = &q931_exp_policy,
};
static unsigned char *get_udp_data(struct sk_buff *skb, unsigned int protoff,
@@ -1234,7 +1222,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
&ct->tuplehash[!dir].tuple.src.u3 : NULL,
&ct->tuplehash[!dir].tuple.dst.u3,
IPPROTO_TCP, NULL, &port);
- rcu_assign_pointer(exp->assign_helper, nf_conntrack_helper_q931);
+ rcu_assign_pointer(exp->assign_helper, &nf_conntrack_helper_q931);
exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */
nathook = rcu_dereference(nfct_h323_nat_hook);
@@ -1306,7 +1294,7 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
&ct->tuplehash[!dir].tuple.src.u3, &addr,
IPPROTO_UDP, NULL, &port);
- rcu_assign_pointer(exp->assign_helper, nf_conntrack_helper_ras);
+ rcu_assign_pointer(exp->assign_helper, &nf_conntrack_helper_ras);
if (nf_ct_expect_related(exp, 0) == 0) {
pr_debug("nf_ct_ras: expect RAS ");
@@ -1523,7 +1511,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
&ct->tuplehash[!dir].tuple.src.u3, &addr,
IPPROTO_TCP, NULL, &port);
exp->flags = NF_CT_EXPECT_PERMANENT;
- rcu_assign_pointer(exp->assign_helper, nf_conntrack_helper_q931);
+ rcu_assign_pointer(exp->assign_helper, &nf_conntrack_helper_q931);
if (nf_ct_expect_related(exp, 0) == 0) {
pr_debug("nf_ct_ras: expect Q.931 ");
@@ -1577,7 +1565,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
&ct->tuplehash[!dir].tuple.src.u3, &addr,
IPPROTO_TCP, NULL, &port);
exp->flags = NF_CT_EXPECT_PERMANENT;
- rcu_assign_pointer(exp->assign_helper, nf_conntrack_helper_q931);
+ rcu_assign_pointer(exp->assign_helper, &nf_conntrack_helper_q931);
if (nf_ct_expect_related(exp, 0) == 0) {
pr_debug("nf_ct_ras: expect Q.931 ");
@@ -1711,25 +1699,13 @@ static const struct nf_conntrack_expect_policy ras_exp_policy = {
.timeout = 240,
};
-static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = {
- {
- .name = "RAS",
- .me = THIS_MODULE,
- .tuple.src.l3num = AF_INET,
- .tuple.src.u.udp.port = cpu_to_be16(RAS_PORT),
- .tuple.dst.protonum = IPPROTO_UDP,
- .help = ras_help,
- .expect_policy = &ras_exp_policy,
- },
- {
- .name = "RAS",
- .me = THIS_MODULE,
- .tuple.src.l3num = AF_INET6,
- .tuple.src.u.udp.port = cpu_to_be16(RAS_PORT),
- .tuple.dst.protonum = IPPROTO_UDP,
- .help = ras_help,
- .expect_policy = &ras_exp_policy,
- },
+static struct nf_conntrack_helper nf_conntrack_helper_ras __read_mostly = {
+ .name = "RAS",
+ .me = THIS_MODULE,
+ .nfproto = NFPROTO_UNSPEC,
+ .l4proto = IPPROTO_UDP,
+ .help = ras_help,
+ .expect_policy = &ras_exp_policy,
};
static int __init h323_helper_init(void)
@@ -1739,19 +1715,16 @@ static int __init h323_helper_init(void)
ret = nf_conntrack_helper_register(&nf_conntrack_helper_h245);
if (ret < 0)
return ret;
- ret = nf_conntrack_helpers_register(nf_conntrack_helper_q931,
- ARRAY_SIZE(nf_conntrack_helper_q931));
+ ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931);
if (ret < 0)
goto err1;
- ret = nf_conntrack_helpers_register(nf_conntrack_helper_ras,
- ARRAY_SIZE(nf_conntrack_helper_ras));
+ ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras);
if (ret < 0)
goto err2;
return 0;
err2:
- nf_conntrack_helpers_unregister(nf_conntrack_helper_q931,
- ARRAY_SIZE(nf_conntrack_helper_q931));
+ nf_conntrack_helper_unregister(&nf_conntrack_helper_q931);
err1:
nf_conntrack_helper_unregister(&nf_conntrack_helper_h245);
return ret;
@@ -1759,10 +1732,8 @@ static int __init h323_helper_init(void)
static void __exit h323_helper_exit(void)
{
- nf_conntrack_helpers_unregister(nf_conntrack_helper_ras,
- ARRAY_SIZE(nf_conntrack_helper_ras));
- nf_conntrack_helpers_unregister(nf_conntrack_helper_q931,
- ARRAY_SIZE(nf_conntrack_helper_q931));
+ nf_conntrack_helper_unregister(&nf_conntrack_helper_ras);
+ nf_conntrack_helper_unregister(&nf_conntrack_helper_q931);
nf_conntrack_helper_unregister(&nf_conntrack_helper_h245);
}
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 32f64f600417..8bf283613c8c 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -61,12 +61,9 @@ __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum)
hlist_for_each_entry_rcu(h, &nf_ct_helper_hash[i], hnode) {
if (strcmp(h->name, name))
continue;
-
- if (h->tuple.src.l3num != NFPROTO_UNSPEC &&
- h->tuple.src.l3num != l3num)
+ if (h->nfproto != NFPROTO_UNSPEC && h->nfproto != l3num)
continue;
-
- if (h->tuple.dst.protonum == protonum)
+ if (h->l4proto == protonum)
return h;
}
return NULL;
@@ -348,7 +345,7 @@ EXPORT_SYMBOL_GPL(nf_ct_helper_log);
int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
{
- unsigned int h = helper_hash(me->name, me->tuple.dst.protonum);
+ unsigned int h = helper_hash(me->name, me->l4proto);
struct nf_conntrack_helper *cur;
int ret = 0;
@@ -365,9 +362,9 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
mutex_lock(&nf_ct_helper_mutex);
hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) {
if (!strcmp(cur->name, me->name) &&
- (cur->tuple.src.l3num == NFPROTO_UNSPEC ||
- cur->tuple.src.l3num == me->tuple.src.l3num) &&
- cur->tuple.dst.protonum == me->tuple.dst.protonum) {
+ (cur->nfproto == NFPROTO_UNSPEC ||
+ cur->nfproto == me->nfproto) &&
+ cur->l4proto == me->l4proto) {
ret = -EBUSY;
goto out;
}
@@ -431,9 +428,8 @@ void nf_ct_helper_init(struct nf_conntrack_helper *helper,
struct nf_conn *ct),
struct module *module)
{
- helper->tuple.src.l3num = l3num;
- helper->tuple.dst.protonum = protonum;
- helper->tuple.src.u.all = htons(spec_port);
+ helper->nfproto = l3num;
+ helper->l4proto = protonum;
helper->expect_policy = exp_pol;
helper->expect_class_max = expect_class_max;
helper->help = help;
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c
index 55415f011943..06cb7ebc5818 100644
--- a/net/netfilter/nf_conntrack_netbios_ns.c
+++ b/net/netfilter/nf_conntrack_netbios_ns.c
@@ -33,7 +33,7 @@ static unsigned int timeout __read_mostly = 3;
module_param(timeout, uint, 0400);
MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
-static struct nf_conntrack_expect_policy exp_policy = {
+static struct nf_conntrack_expect_policy exp_policy __ro_after_init = {
.max_expected = 1,
};
@@ -46,9 +46,8 @@ static int netbios_ns_help(struct sk_buff *skb, unsigned int protoff,
static struct nf_conntrack_helper helper __read_mostly = {
.name = HELPER_NAME,
- .tuple.src.l3num = NFPROTO_IPV4,
- .tuple.src.u.udp.port = cpu_to_be16(NMBD_PORT),
- .tuple.dst.protonum = IPPROTO_UDP,
+ .nfproto = NFPROTO_IPV4,
+ .l4proto = IPPROTO_UDP,
.me = THIS_MODULE,
.help = netbios_ns_help,
.expect_policy = &exp_policy,
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 4c679638df06..c079d4db52b8 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -589,9 +589,8 @@ static const struct nf_conntrack_expect_policy pptp_exp_policy = {
static struct nf_conntrack_helper pptp __read_mostly = {
.name = "pptp",
.me = THIS_MODULE,
- .tuple.src.l3num = AF_INET,
- .tuple.src.u.tcp.port = cpu_to_be16(PPTP_CONTROL_PORT),
- .tuple.dst.protonum = IPPROTO_TCP,
+ .nfproto = NFPROTO_IPV4,
+ .l4proto = IPPROTO_TCP,
.help = conntrack_pptp_help,
.destroy = pptp_destroy_siblings,
.expect_policy = &pptp_exp_policy,
diff --git a/net/netfilter/nf_conntrack_snmp.c b/net/netfilter/nf_conntrack_snmp.c
index 7b7eed43c54f..18342e1af989 100644
--- a/net/netfilter/nf_conntrack_snmp.c
+++ b/net/netfilter/nf_conntrack_snmp.c
@@ -43,15 +43,14 @@ static int snmp_conntrack_help(struct sk_buff *skb, unsigned int protoff,
return NF_ACCEPT;
}
-static struct nf_conntrack_expect_policy exp_policy = {
+static struct nf_conntrack_expect_policy exp_policy __ro_after_init = {
.max_expected = 1,
};
static struct nf_conntrack_helper helper __read_mostly = {
.name = "snmp",
- .tuple.src.l3num = NFPROTO_IPV4,
- .tuple.src.u.udp.port = cpu_to_be16(SNMP_PORT),
- .tuple.dst.protonum = IPPROTO_UDP,
+ .nfproto = NFPROTO_IPV4,
+ .l4proto = IPPROTO_UDP,
.me = THIS_MODULE,
.help = snmp_conntrack_help,
.expect_policy = &exp_policy,
diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c
index 0d16ad82d70c..805c4711926c 100644
--- a/net/netfilter/nfnetlink_cthelper.c
+++ b/net/netfilter/nfnetlink_cthelper.c
@@ -246,8 +246,8 @@ nfnl_cthelper_create(const struct nlattr * const tb[],
helper->data_len = size;
helper->flags |= NF_CT_HELPER_F_USERSPACE;
- memcpy(&helper->tuple, tuple, sizeof(struct nf_conntrack_tuple));
-
+ helper->nfproto = tuple->src.l3num;
+ helper->l4proto = tuple->dst.protonum;
helper->me = THIS_MODULE;
helper->help = nfnl_userspace_cthelper;
helper->from_nlattr = nfnl_cthelper_from_nlattr;
@@ -441,8 +441,8 @@ static int nfnl_cthelper_new(struct sk_buff *skb, const struct nfnl_info *info,
if (strncmp(cur->name, helper_name, NF_CT_HELPER_NAME_LEN))
continue;
- if ((tuple.src.l3num != cur->tuple.src.l3num ||
- tuple.dst.protonum != cur->tuple.dst.protonum))
+ if (tuple.src.l3num != cur->nfproto ||
+ tuple.dst.protonum != cur->l4proto)
continue;
if (info->nlh->nlmsg_flags & NLM_F_EXCL)
@@ -471,10 +471,10 @@ nfnl_cthelper_dump_tuple(struct sk_buff *skb,
goto nla_put_failure;
if (nla_put_be16(skb, NFCTH_TUPLE_L3PROTONUM,
- htons(helper->tuple.src.l3num)))
+ htons(helper->nfproto)))
goto nla_put_failure;
- if (nla_put_u8(skb, NFCTH_TUPLE_L4PROTONUM, helper->tuple.dst.protonum))
+ if (nla_put_u8(skb, NFCTH_TUPLE_L4PROTONUM, helper->l4proto))
goto nla_put_failure;
nla_nest_end(skb, nest_parms);
@@ -650,8 +650,8 @@ static int nfnl_cthelper_get(struct sk_buff *skb, const struct nfnl_info *info,
continue;
if (tuple_set &&
- (tuple.src.l3num != cur->tuple.src.l3num ||
- tuple.dst.protonum != cur->tuple.dst.protonum))
+ (tuple.src.l3num != cur->nfproto ||
+ tuple.dst.protonum != cur->l4proto))
continue;
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
@@ -710,8 +710,8 @@ static int nfnl_cthelper_del(struct sk_buff *skb, const struct nfnl_info *info,
continue;
if (tuple_set &&
- (tuple.src.l3num != cur->tuple.src.l3num ||
- tuple.dst.protonum != cur->tuple.dst.protonum))
+ (tuple.src.l3num != cur->nfproto ||
+ tuple.dst.protonum != cur->l4proto))
continue;
if (refcount_dec_if_one(&cur->refcnt)) {
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH nf-next 3/5] netfilter: nf_conntrack: switch to static registration
2026-05-22 5:01 [PATCH nf-next 0/5] netfilter: conntrack: remove some code Florian Westphal
2026-05-22 5:01 ` [PATCH nf-next 1/5] netfilter: nf_conntrack_helper: do not hash by tuple Florian Westphal
2026-05-22 5:01 ` [PATCH nf-next 2/5] netfilter: conntrack: get rid of tuple in helper definitions Florian Westphal
@ 2026-05-22 5:01 ` Florian Westphal
2026-05-22 5:01 ` [PATCH nf-next 4/5] netfilter: remove obsolete nf_ct_helper_init api Florian Westphal
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2026-05-22 5:01 UTC (permalink / raw)
To: netfilter-devel; +Cc: Florian Westphal
helper autoassign was removed years ago, one instance is enough.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
net/netfilter/nf_conntrack_ftp.c | 51 +++++++-------------------
net/netfilter/nf_conntrack_irc.c | 38 ++++++++-----------
net/netfilter/nf_conntrack_sane.c | 50 +++++++------------------
net/netfilter/nf_conntrack_sip.c | 61 +++++++++++--------------------
net/netfilter/nf_conntrack_tftp.c | 47 +++++++-----------------
5 files changed, 77 insertions(+), 170 deletions(-)
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index de83bf9e6c61..c9dadfef81ba 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -35,11 +35,6 @@ MODULE_ALIAS("ip_conntrack_ftp");
MODULE_ALIAS_NFCT_HELPER(HELPER_NAME);
static DEFINE_SPINLOCK(nf_ftp_lock);
-#define MAX_PORTS 8
-static u_int16_t ports[MAX_PORTS];
-static unsigned int ports_c;
-module_param_array(ports, ushort, &ports_c, 0400);
-
static bool loose;
module_param(loose, bool, 0600);
@@ -360,10 +355,8 @@ static void update_nl_seq(struct nf_conn *ct, u32 nl_seq,
}
}
-static int help(struct sk_buff *skb,
- unsigned int protoff,
- struct nf_conn *ct,
- enum ip_conntrack_info ctinfo)
+static int ftp_help(struct sk_buff *skb, unsigned int protoff,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
{
unsigned int dataoff, datalen;
const struct tcphdr *th;
@@ -551,47 +544,31 @@ static int nf_ct_ftp_from_nlattr(struct nlattr *attr, struct nf_conn *ct)
return 0;
}
-static struct nf_conntrack_helper ftp[MAX_PORTS * 2] __read_mostly;
-
static const struct nf_conntrack_expect_policy ftp_exp_policy = {
.max_expected = 1,
.timeout = 5 * 60,
};
+static struct nf_conntrack_helper ftp __read_mostly = {
+ .name = HELPER_NAME,
+ .me = THIS_MODULE,
+ .nfproto = NFPROTO_UNSPEC,
+ .l4proto = IPPROTO_TCP,
+ .help = ftp_help,
+ .expect_policy = &ftp_exp_policy,
+ .from_nlattr = nf_ct_ftp_from_nlattr,
+};
+
static void __exit nf_conntrack_ftp_fini(void)
{
- nf_conntrack_helpers_unregister(ftp, ports_c * 2);
+ nf_conntrack_helper_unregister(&ftp);
}
static int __init nf_conntrack_ftp_init(void)
{
- int i, ret = 0;
-
NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_ftp_master));
- if (ports_c == 0)
- ports[ports_c++] = FTP_PORT;
-
- /* FIXME should be configurable whether IPv4 and IPv6 FTP connections
- are tracked or not - YK */
- for (i = 0; i < ports_c; i++) {
- nf_ct_helper_init(&ftp[2 * i], AF_INET, IPPROTO_TCP,
- HELPER_NAME, FTP_PORT, ports[i], ports[i],
- &ftp_exp_policy, 0, help,
- nf_ct_ftp_from_nlattr, THIS_MODULE);
- nf_ct_helper_init(&ftp[2 * i + 1], AF_INET6, IPPROTO_TCP,
- HELPER_NAME, FTP_PORT, ports[i], ports[i],
- &ftp_exp_policy, 0, help,
- nf_ct_ftp_from_nlattr, THIS_MODULE);
- }
-
- ret = nf_conntrack_helpers_register(ftp, ports_c * 2);
- if (ret < 0) {
- pr_err("failed to register helpers\n");
- return ret;
- }
-
- return 0;
+ return nf_conntrack_helper_register(&ftp);
}
module_init(nf_conntrack_ftp_init);
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index 522183b9a604..4e07963a5c73 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -21,9 +21,6 @@
#include <net/netfilter/nf_conntrack_helper.h>
#include <linux/netfilter/nf_conntrack_irc.h>
-#define MAX_PORTS 8
-static unsigned short ports[MAX_PORTS];
-static unsigned int ports_c;
static unsigned int max_dcc_channels = 8;
static unsigned int dcc_timeout __read_mostly = 300;
/* This is slow, but it's simple. --RR */
@@ -42,8 +39,6 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("ip_conntrack_irc");
MODULE_ALIAS_NFCT_HELPER(HELPER_NAME);
-module_param_array(ports, ushort, &ports_c, 0400);
-MODULE_PARM_DESC(ports, "port numbers of IRC servers");
module_param(max_dcc_channels, uint, 0400);
MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per "
"IRC session");
@@ -99,8 +94,8 @@ static int parse_dcc(char *data, const char *data_end, __be32 *ip,
return 0;
}
-static int help(struct sk_buff *skb, unsigned int protoff,
- struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+static int irc_help(struct sk_buff *skb, unsigned int protoff,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
{
unsigned int dataoff;
const struct iphdr *iph;
@@ -254,12 +249,20 @@ static int help(struct sk_buff *skb, unsigned int protoff,
return ret;
}
-static struct nf_conntrack_helper irc[MAX_PORTS] __read_mostly;
-static struct nf_conntrack_expect_policy irc_exp_policy;
+static struct nf_conntrack_expect_policy irc_exp_policy __ro_after_init;
+
+static struct nf_conntrack_helper irc __read_mostly = {
+ .name = HELPER_NAME,
+ .me = THIS_MODULE,
+ .help = irc_help,
+ .nfproto = NFPROTO_IPV4,
+ .l4proto = IPPROTO_TCP,
+ .expect_policy = &irc_exp_policy,
+};
static int __init nf_conntrack_irc_init(void)
{
- int i, ret;
+ int ret;
if (max_dcc_channels < 1) {
pr_err("max_dcc_channels must not be zero\n");
@@ -279,19 +282,8 @@ static int __init nf_conntrack_irc_init(void)
if (!irc_buffer)
return -ENOMEM;
- /* If no port given, default to standard irc port */
- if (ports_c == 0)
- ports[ports_c++] = IRC_PORT;
-
- for (i = 0; i < ports_c; i++) {
- nf_ct_helper_init(&irc[i], AF_INET, IPPROTO_TCP, HELPER_NAME,
- IRC_PORT, ports[i], i, &irc_exp_policy,
- 0, help, NULL, THIS_MODULE);
- }
-
- ret = nf_conntrack_helpers_register(&irc[0], ports_c);
+ ret = nf_conntrack_helper_register(&irc);
if (ret) {
- pr_err("failed to register helpers\n");
kfree(irc_buffer);
return ret;
}
@@ -301,7 +293,7 @@ static int __init nf_conntrack_irc_init(void)
static void __exit nf_conntrack_irc_fini(void)
{
- nf_conntrack_helpers_unregister(irc, ports_c);
+ nf_conntrack_helper_unregister(&irc);
kfree(irc_buffer);
}
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c
index 13dc421fc4f5..db52a045ce5d 100644
--- a/net/netfilter/nf_conntrack_sane.c
+++ b/net/netfilter/nf_conntrack_sane.c
@@ -34,11 +34,6 @@ MODULE_AUTHOR("Michal Schmidt <mschmidt@redhat.com>");
MODULE_DESCRIPTION("SANE connection tracking helper");
MODULE_ALIAS_NFCT_HELPER(HELPER_NAME);
-#define MAX_PORTS 8
-static u_int16_t ports[MAX_PORTS];
-static unsigned int ports_c;
-module_param_array(ports, ushort, &ports_c, 0400);
-
struct sane_request {
__be32 RPC_code;
#define SANE_NET_START 7 /* RPC code */
@@ -55,10 +50,8 @@ struct sane_reply_net_start {
/* other fields aren't interesting for conntrack */
};
-static int help(struct sk_buff *skb,
- unsigned int protoff,
- struct nf_conn *ct,
- enum ip_conntrack_info ctinfo)
+static int sane_help(struct sk_buff *skb, unsigned int protoff,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
{
unsigned int dataoff, datalen;
const struct tcphdr *th;
@@ -166,47 +159,30 @@ static int help(struct sk_buff *skb,
return ret;
}
-static struct nf_conntrack_helper sane[MAX_PORTS * 2] __read_mostly;
-
static const struct nf_conntrack_expect_policy sane_exp_policy = {
.max_expected = 1,
.timeout = 5 * 60,
};
+static struct nf_conntrack_helper sane __read_mostly = {
+ .name = HELPER_NAME,
+ .me = THIS_MODULE,
+ .nfproto = NFPROTO_UNSPEC,
+ .l4proto = IPPROTO_TCP,
+ .help = sane_help,
+ .expect_policy = &sane_exp_policy,
+};
+
static void __exit nf_conntrack_sane_fini(void)
{
- nf_conntrack_helpers_unregister(sane, ports_c * 2);
+ nf_conntrack_helper_unregister(&sane);
}
static int __init nf_conntrack_sane_init(void)
{
- int i, ret = 0;
-
NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_sane_master));
- if (ports_c == 0)
- ports[ports_c++] = SANE_PORT;
-
- /* FIXME should be configurable whether IPv4 and IPv6 connections
- are tracked or not - YK */
- for (i = 0; i < ports_c; i++) {
- nf_ct_helper_init(&sane[2 * i], AF_INET, IPPROTO_TCP,
- HELPER_NAME, SANE_PORT, ports[i], ports[i],
- &sane_exp_policy, 0, help, NULL,
- THIS_MODULE);
- nf_ct_helper_init(&sane[2 * i + 1], AF_INET6, IPPROTO_TCP,
- HELPER_NAME, SANE_PORT, ports[i], ports[i],
- &sane_exp_policy, 0, help, NULL,
- THIS_MODULE);
- }
-
- ret = nf_conntrack_helpers_register(sane, ports_c * 2);
- if (ret < 0) {
- pr_err("failed to register helpers\n");
- return ret;
- }
-
- return 0;
+ return nf_conntrack_helper_register(&sane);
}
module_init(nf_conntrack_sane_init);
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index e69941f1a101..aca24d8dbfbc 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -35,12 +35,6 @@ MODULE_DESCRIPTION("SIP connection tracking helper");
MODULE_ALIAS("ip_conntrack_sip");
MODULE_ALIAS_NFCT_HELPER(HELPER_NAME);
-#define MAX_PORTS 8
-static unsigned short ports[MAX_PORTS];
-static unsigned int ports_c;
-module_param_array(ports, ushort, &ports_c, 0400);
-MODULE_PARM_DESC(ports, "port numbers of SIP servers");
-
static unsigned int sip_timeout __read_mostly = SIP_TIMEOUT;
module_param(sip_timeout, uint, 0600);
MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session");
@@ -1730,8 +1724,6 @@ static int sip_help_udp(struct sk_buff *skb, unsigned int protoff,
return process_sip_msg(skb, ct, protoff, dataoff, &dptr, &datalen);
}
-static struct nf_conntrack_helper sip[MAX_PORTS * 4] __read_mostly;
-
static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = {
[SIP_EXPECT_SIGNALLING] = {
.name = "signalling",
@@ -1755,45 +1747,36 @@ static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1
},
};
+static struct nf_conntrack_helper sip[] __read_mostly = {
+ {
+ .name = HELPER_NAME,
+ .me = THIS_MODULE,
+ .nfproto = NFPROTO_UNSPEC,
+ .l4proto = IPPROTO_TCP,
+ .help = sip_help_tcp,
+ .expect_policy = sip_exp_policy,
+ .expect_class_max = SIP_EXPECT_MAX,
+ }, {
+ .name = HELPER_NAME,
+ .me = THIS_MODULE,
+ .nfproto = NFPROTO_UNSPEC,
+ .l4proto = IPPROTO_UDP,
+ .help = sip_help_udp,
+ .expect_policy = sip_exp_policy,
+ .expect_class_max = SIP_EXPECT_MAX,
+ }
+};
+
static void __exit nf_conntrack_sip_fini(void)
{
- nf_conntrack_helpers_unregister(sip, ports_c * 4);
+ nf_conntrack_helpers_unregister(sip, ARRAY_SIZE(sip));
}
static int __init nf_conntrack_sip_init(void)
{
- int i, ret;
-
NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_sip_master));
- if (ports_c == 0)
- ports[ports_c++] = SIP_PORT;
-
- for (i = 0; i < ports_c; i++) {
- nf_ct_helper_init(&sip[4 * i], AF_INET, IPPROTO_UDP,
- HELPER_NAME, SIP_PORT, ports[i], i,
- sip_exp_policy, SIP_EXPECT_MAX, sip_help_udp,
- NULL, THIS_MODULE);
- nf_ct_helper_init(&sip[4 * i + 1], AF_INET, IPPROTO_TCP,
- HELPER_NAME, SIP_PORT, ports[i], i,
- sip_exp_policy, SIP_EXPECT_MAX, sip_help_tcp,
- NULL, THIS_MODULE);
- nf_ct_helper_init(&sip[4 * i + 2], AF_INET6, IPPROTO_UDP,
- HELPER_NAME, SIP_PORT, ports[i], i,
- sip_exp_policy, SIP_EXPECT_MAX, sip_help_udp,
- NULL, THIS_MODULE);
- nf_ct_helper_init(&sip[4 * i + 3], AF_INET6, IPPROTO_TCP,
- HELPER_NAME, SIP_PORT, ports[i], i,
- sip_exp_policy, SIP_EXPECT_MAX, sip_help_tcp,
- NULL, THIS_MODULE);
- }
-
- ret = nf_conntrack_helpers_register(sip, ports_c * 4);
- if (ret < 0) {
- pr_err("failed to register helpers\n");
- return ret;
- }
- return 0;
+ return nf_conntrack_helpers_register(sip, ARRAY_SIZE(sip));
}
module_init(nf_conntrack_sip_init);
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c
index a2e6833a0bf7..aaa048c72b6c 100644
--- a/net/netfilter/nf_conntrack_tftp.c
+++ b/net/netfilter/nf_conntrack_tftp.c
@@ -26,12 +26,6 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("ip_conntrack_tftp");
MODULE_ALIAS_NFCT_HELPER(HELPER_NAME);
-#define MAX_PORTS 8
-static unsigned short ports[MAX_PORTS];
-static unsigned int ports_c;
-module_param_array(ports, ushort, &ports_c, 0400);
-MODULE_PARM_DESC(ports, "Port numbers of TFTP servers");
-
nf_nat_tftp_hook_fn __rcu *nf_nat_tftp_hook __read_mostly;
EXPORT_SYMBOL_GPL(nf_nat_tftp_hook);
@@ -95,45 +89,30 @@ static int tftp_help(struct sk_buff *skb,
return ret;
}
-static struct nf_conntrack_helper tftp[MAX_PORTS * 2] __read_mostly;
-
static const struct nf_conntrack_expect_policy tftp_exp_policy = {
.max_expected = 1,
.timeout = 5 * 60,
};
-static void __exit nf_conntrack_tftp_fini(void)
-{
- nf_conntrack_helpers_unregister(tftp, ports_c * 2);
-}
+static struct nf_conntrack_helper tftp __read_mostly = {
+ .name = HELPER_NAME,
+ .me = THIS_MODULE,
+ .nfproto = NFPROTO_UNSPEC,
+ .l4proto = IPPROTO_UDP,
+ .help = tftp_help,
+ .expect_policy = &tftp_exp_policy,
+};
static int __init nf_conntrack_tftp_init(void)
{
- int i, ret;
-
NF_CT_HELPER_BUILD_BUG_ON(0);
- if (ports_c == 0)
- ports[ports_c++] = TFTP_PORT;
-
- for (i = 0; i < ports_c; i++) {
- nf_ct_helper_init(&tftp[2 * i], AF_INET, IPPROTO_UDP,
- HELPER_NAME, TFTP_PORT, ports[i], i,
- &tftp_exp_policy, 0, tftp_help, NULL,
- THIS_MODULE);
- nf_ct_helper_init(&tftp[2 * i + 1], AF_INET6, IPPROTO_UDP,
- HELPER_NAME, TFTP_PORT, ports[i], i,
- &tftp_exp_policy, 0, tftp_help, NULL,
- THIS_MODULE);
- }
-
- ret = nf_conntrack_helpers_register(tftp, ports_c * 2);
- if (ret < 0) {
- pr_err("failed to register helpers\n");
- return ret;
- }
- return 0;
+ return nf_conntrack_helper_register(&tftp);
}
+static void __exit nf_conntrack_tftp_fini(void)
+{
+ nf_conntrack_helper_unregister(&tftp);
+}
module_init(nf_conntrack_tftp_init);
module_exit(nf_conntrack_tftp_fini);
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH nf-next 4/5] netfilter: remove obsolete nf_ct_helper_init api
2026-05-22 5:01 [PATCH nf-next 0/5] netfilter: conntrack: remove some code Florian Westphal
` (2 preceding siblings ...)
2026-05-22 5:01 ` [PATCH nf-next 3/5] netfilter: nf_conntrack: switch to static registration Florian Westphal
@ 2026-05-22 5:01 ` Florian Westphal
2026-05-22 5:01 ` [PATCH nf-next 5/5] netfilter: conntrack: add deprecation warnings for irc and pptp trackers Florian Westphal
2026-05-23 6:28 ` [PATCH nf-next 0/5] netfilter: conntrack: remove some code Pablo Neira Ayuso
5 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2026-05-22 5:01 UTC (permalink / raw)
To: netfilter-devel; +Cc: Florian Westphal
No more in-tree users.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/net/netfilter/nf_conntrack_helper.h | 12 ---------
net/netfilter/nf_conntrack_helper.c | 29 ---------------------
2 files changed, 41 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index ab41ff60e9d1..2e1fea8b0a8d 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -91,18 +91,6 @@ struct nf_conntrack_helper *nf_conntrack_helper_try_module_get(const char *name,
u8 protonum);
void nf_conntrack_helper_put(struct nf_conntrack_helper *helper);
-void nf_ct_helper_init(struct nf_conntrack_helper *helper,
- u16 l3num, u16 protonum, const char *name,
- u16 default_port, u16 spec_port, u32 id,
- const struct nf_conntrack_expect_policy *exp_pol,
- u32 expect_class_max,
- int (*help)(struct sk_buff *skb, unsigned int protoff,
- struct nf_conn *ct,
- enum ip_conntrack_info ctinfo),
- int (*from_nlattr)(struct nlattr *attr,
- struct nf_conn *ct),
- struct module *module);
-
int nf_conntrack_helper_register(struct nf_conntrack_helper *);
void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 8bf283613c8c..44345d9e834e 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -416,35 +416,6 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
}
EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);
-void nf_ct_helper_init(struct nf_conntrack_helper *helper,
- u16 l3num, u16 protonum, const char *name,
- u16 default_port, u16 spec_port, u32 id,
- const struct nf_conntrack_expect_policy *exp_pol,
- u32 expect_class_max,
- int (*help)(struct sk_buff *skb, unsigned int protoff,
- struct nf_conn *ct,
- enum ip_conntrack_info ctinfo),
- int (*from_nlattr)(struct nlattr *attr,
- struct nf_conn *ct),
- struct module *module)
-{
- helper->nfproto = l3num;
- helper->l4proto = protonum;
- helper->expect_policy = exp_pol;
- helper->expect_class_max = expect_class_max;
- helper->help = help;
- helper->from_nlattr = from_nlattr;
- helper->me = module;
- snprintf(helper->nat_mod_name, sizeof(helper->nat_mod_name),
- NF_NAT_HELPER_PREFIX "%s", name);
-
- if (spec_port == default_port)
- snprintf(helper->name, sizeof(helper->name), "%s", name);
- else
- snprintf(helper->name, sizeof(helper->name), "%s-%u", name, id);
-}
-EXPORT_SYMBOL_GPL(nf_ct_helper_init);
-
int nf_conntrack_helpers_register(struct nf_conntrack_helper *helper,
unsigned int n)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH nf-next 5/5] netfilter: conntrack: add deprecation warnings for irc and pptp trackers
2026-05-22 5:01 [PATCH nf-next 0/5] netfilter: conntrack: remove some code Florian Westphal
` (3 preceding siblings ...)
2026-05-22 5:01 ` [PATCH nf-next 4/5] netfilter: remove obsolete nf_ct_helper_init api Florian Westphal
@ 2026-05-22 5:01 ` Florian Westphal
2026-05-23 6:28 ` [PATCH nf-next 0/5] netfilter: conntrack: remove some code Pablo Neira Ayuso
5 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2026-05-22 5:01 UTC (permalink / raw)
To: netfilter-devel; +Cc: Florian Westphal
IRC Direct client-to-client requires plaintext. IRC over TLS should be
preferred, making this helper ineffective. Add a deprecation warning and
update the help text to better reflect that this is needed for the DCC
extenion, not IRC itself.
PPTP is esoteric these days and it is the only helper that requires the
destroy callback in the conntrack helper API.
Removal would simplify the conntrack core.
Both helpers are IPv4 only as well.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/net/netfilter/nf_conntrack_helper.h | 4 ++++
net/netfilter/Kconfig | 11 ++++++-----
net/netfilter/nf_conntrack_irc.c | 2 ++
net/netfilter/nf_conntrack_pptp.c | 2 ++
4 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 2e1fea8b0a8d..9e7bea89de92 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -98,6 +98,10 @@ int nf_conntrack_helpers_register(struct nf_conntrack_helper *, unsigned int);
void nf_conntrack_helpers_unregister(struct nf_conntrack_helper *,
unsigned int);
+#define nf_conntrack_helper_deprecated(name) \
+ pr_warn("The %s conntrack helper is scheduled for removal.\n" \
+ "Please contact the netfilter-devel mailing list if you still need this.\n", name)
+
struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp);
int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 682c675125fc..133f03d90c0f 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -256,8 +256,7 @@ config NF_CONNTRACK_H323
To compile it as a module, choose M here. If unsure, say N.
config NF_CONNTRACK_IRC
- tristate "IRC protocol support"
- default m if NETFILTER_ADVANCED=n
+ tristate "IRC DCC protocol support (obsolete)"
help
There is a commonly-used extension to IRC called
Direct Client-to-Client Protocol (DCC). This enables users to send
@@ -267,6 +266,8 @@ config NF_CONNTRACK_IRC
using NAT, this extension will enable you to send files and initiate
chats. Note that you do NOT need this extension to get files or
have others initiate chats, or everything else in IRC.
+ DCC tracking behind NAT requires plaintext (unencrypted) IRC, so
+ this helper is of limited use these days.
To compile it as a module, choose M here. If unsure, say N.
@@ -308,17 +309,17 @@ config NF_CONNTRACK_SNMP
To compile it as a module, choose M here. If unsure, say N.
config NF_CONNTRACK_PPTP
- tristate "PPtP protocol support"
+ tristate "PPtP protocol support (deprecated)"
depends on NETFILTER_ADVANCED
select NF_CT_PROTO_GRE
help
This module adds support for PPTP (Point to Point Tunnelling
Protocol, RFC2637) connection tracking and NAT.
- If you are running PPTP sessions over a stateful firewall or NAT
+ If you are still running PPTP sessions over a stateful firewall or NAT
box, you may want to enable this feature.
- Please note that not all PPTP modes of operation are supported yet.
+ Please note that not all PPTP modes of operation are supported.
Specifically these limitations exist:
- Blindly assumes that control connections are always established
in PNS->PAC direction. This is a violation of RFC2637.
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index 4e07963a5c73..cebf73f34c77 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -264,6 +264,8 @@ static int __init nf_conntrack_irc_init(void)
{
int ret;
+ nf_conntrack_helper_deprecated(HELPER_NAME);
+
if (max_dcc_channels < 1) {
pr_err("max_dcc_channels must not be zero\n");
return -EINVAL;
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index c079d4db52b8..afb67a31ab26 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -600,6 +600,8 @@ static int __init nf_conntrack_pptp_init(void)
{
NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_pptp_master));
+ nf_conntrack_helper_deprecated(pptp.name);
+
return nf_conntrack_helper_register(&pptp);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH nf-next 0/5] netfilter: conntrack: remove some code
2026-05-22 5:01 [PATCH nf-next 0/5] netfilter: conntrack: remove some code Florian Westphal
` (4 preceding siblings ...)
2026-05-22 5:01 ` [PATCH nf-next 5/5] netfilter: conntrack: add deprecation warnings for irc and pptp trackers Florian Westphal
@ 2026-05-23 6:28 ` Pablo Neira Ayuso
2026-05-23 7:26 ` Florian Westphal
5 siblings, 1 reply; 9+ messages in thread
From: Pablo Neira Ayuso @ 2026-05-23 6:28 UTC (permalink / raw)
To: Florian Westphal; +Cc: netfilter-devel
Hi Florian,
Thanks for your series.
I have been working this week on fixing the helper infrastructure as I
told you, my series is directly clashing with this.
It's is taking me a bit of time to make sure to validate this is
correct but I can hopefully post it asap.
If you can only on with this series, I'd appreciate.
Thanks
On Fri, May 22, 2026 at 07:01:29AM +0200, Florian Westphal wrote:
> 1) Remove the full tuple from the nf_conntrack_helper hash. Switch to hashing
> based on the helper name and L4 protocol.
>
> 2) Remove tuple from netfilter conntrack helper definitions. Eliminate
> redundant IPv4 and IPv6 registration requests.
>
> 3) Switch nf_conntrack to static registration. Remove helper autoassign
> port module params.
>
> 4) Remove the obsolete nf_ct_helper_init API from netfilter.
>
> 5) Add deprecation warnings for IRC and PPTP conntrack trackers. Update IRC
> helper help text to clarify its use for DCC extension.
>
> Florian Westphal (5):
> netfilter: nf_conntrack_helper: do not hash by tuple
> netfilter: conntrack: get rid of tuple in helper definitions
> netfilter: nf_conntrack: switch to static registration
> netfilter: remove obsolete nf_ct_helper_init api
> netfilter: conntrack: add deprecation warnings for irc and pptp trackers
>
> include/net/netfilter/nf_conntrack_helper.h | 20 ++---
> net/ipv4/netfilter/nf_nat_snmp_basic_main.c | 5 +-
> net/netfilter/Kconfig | 11 +--
> net/netfilter/nf_conntrack_amanda.c | 35 +++-----
> net/netfilter/nf_conntrack_broadcast.c | 2 -
> net/netfilter/nf_conntrack_ftp.c | 51 +++--------
> net/netfilter/nf_conntrack_h323_main.c | 85 ++++++------------
> net/netfilter/nf_conntrack_helper.c | 96 ++++++---------------
> net/netfilter/nf_conntrack_irc.c | 40 ++++-----
> net/netfilter/nf_conntrack_netbios_ns.c | 7 +-
> net/netfilter/nf_conntrack_pptp.c | 7 +-
> net/netfilter/nf_conntrack_sane.c | 50 +++--------
> net/netfilter/nf_conntrack_sip.c | 61 +++++--------
> net/netfilter/nf_conntrack_snmp.c | 7 +-
> net/netfilter/nf_conntrack_tftp.c | 47 +++-------
> net/netfilter/nfnetlink_cthelper.c | 20 ++---
> 16 files changed, 177 insertions(+), 367 deletions(-)
>
> --
> 2.53.0
>
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH nf-next 0/5] netfilter: conntrack: remove some code
2026-05-23 6:28 ` [PATCH nf-next 0/5] netfilter: conntrack: remove some code Pablo Neira Ayuso
@ 2026-05-23 7:26 ` Florian Westphal
2026-05-23 8:28 ` Pablo Neira Ayuso
0 siblings, 1 reply; 9+ messages in thread
From: Florian Westphal @ 2026-05-23 7:26 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> I have been working this week on fixing the helper infrastructure as I
> told you, my series is directly clashing with this.
> It's is taking me a bit of time to make sure to validate this is
> correct but I can hopefully post it asap.
No need to rush, this one needs a new revision anyway. I will wait
until your series is applied before doing a v2.
If you like you can integrate the last patch of this series (irc/pptp
deprecation) into yours, that patch isn' strictly related to the
others.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH nf-next 0/5] netfilter: conntrack: remove some code
2026-05-23 7:26 ` Florian Westphal
@ 2026-05-23 8:28 ` Pablo Neira Ayuso
0 siblings, 0 replies; 9+ messages in thread
From: Pablo Neira Ayuso @ 2026-05-23 8:28 UTC (permalink / raw)
To: Florian Westphal; +Cc: netfilter-devel
On Sat, May 23, 2026 at 09:26:29AM +0200, Florian Westphal wrote:
> Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > I have been working this week on fixing the helper infrastructure as I
> > told you, my series is directly clashing with this.
> > It's is taking me a bit of time to make sure to validate this is
> > correct but I can hopefully post it asap.
>
> No need to rush, this one needs a new revision anyway. I will wait
> until your series is applied before doing a v2.
I am finishing the review and testing, it is a change in the direction
of the previous series to tackle the issues, by dynamically allocating
the timeout and helper and refcnt to track packet path/ct extension
users. I can post this series later today / early morning tomorrow.
> If you like you can integrate the last patch of this series (irc/pptp
> deprecation) into yours, that patch isn' strictly related to the
> others.
Thanks, if my fixes are deemed correct, I'd appreciate that rebase on
top.
^ permalink raw reply [flat|nested] 9+ messages in thread