Skip to content

Commit

Permalink
netfilter: Add helper array register/unregister functions
Browse files Browse the repository at this point in the history
Add nf_ct_helper_init(), nf_conntrack_helpers_register() and
nf_conntrack_helpers_unregister() functions to avoid repetitive
opencoded initialization in helpers.

This patch keeps an id parameter for nf_ct_helper_init() not to break
helper matching by name that has been inconsistently exposed to
userspace through ports, eg. ftp-2121, and through an incremental id,
eg. tftp-1.

Signed-off-by: Gao Feng <fgao@ikuai8.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  • Loading branch information
Gao Feng authored and Pablo Neira Ayuso committed Jul 21, 2016
1 parent 590025a commit 82de0be
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 181 deletions.
15 changes: 15 additions & 0 deletions include/net/netfilter/nf_conntrack_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,25 @@ struct nf_conntrack_helper *__nf_conntrack_helper_find(const char *name,
struct nf_conntrack_helper *nf_conntrack_helper_try_module_get(const char *name,
u16 l3num,
u8 protonum);
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, u32 data_len,
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 *);

int nf_conntrack_helpers_register(struct nf_conntrack_helper *, unsigned int);
void nf_conntrack_helpers_unregister(struct nf_conntrack_helper *,
unsigned int);

struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct,
struct nf_conntrack_helper *helper,
gfp_t gfp);
Expand Down
58 changes: 18 additions & 40 deletions net/netfilter/nf_conntrack_ftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ 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 struct nf_conntrack_helper ftp[MAX_PORTS * 2] __read_mostly;

static const struct nf_conntrack_expect_policy ftp_exp_policy = {
.max_expected = 1,
Expand All @@ -582,24 +582,13 @@ static const struct nf_conntrack_expect_policy ftp_exp_policy = {
/* don't make this __exit, since it's called from __init ! */
static void nf_conntrack_ftp_fini(void)
{
int i, j;
for (i = 0; i < ports_c; i++) {
for (j = 0; j < 2; j++) {
if (ftp[i][j].me == NULL)
continue;

pr_debug("unregistering helper for pf: %d port: %d\n",
ftp[i][j].tuple.src.l3num, ports[i]);
nf_conntrack_helper_unregister(&ftp[i][j]);
}
}

nf_conntrack_helpers_unregister(ftp, ports_c * 2);
kfree(ftp_buffer);
}

static int __init nf_conntrack_ftp_init(void)
{
int i, j = -1, ret = 0;
int i, ret = 0;

ftp_buffer = kmalloc(65536, GFP_KERNEL);
if (!ftp_buffer)
Expand All @@ -611,32 +600,21 @@ static int __init nf_conntrack_ftp_init(void)
/* FIXME should be configurable whether IPv4 and IPv6 FTP connections
are tracked or not - YK */
for (i = 0; i < ports_c; i++) {
ftp[i][0].tuple.src.l3num = PF_INET;
ftp[i][1].tuple.src.l3num = PF_INET6;
for (j = 0; j < 2; j++) {
ftp[i][j].data_len = sizeof(struct nf_ct_ftp_master);
ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]);
ftp[i][j].tuple.dst.protonum = IPPROTO_TCP;
ftp[i][j].expect_policy = &ftp_exp_policy;
ftp[i][j].me = THIS_MODULE;
ftp[i][j].help = help;
ftp[i][j].from_nlattr = nf_ct_ftp_from_nlattr;
if (ports[i] == FTP_PORT)
sprintf(ftp[i][j].name, "ftp");
else
sprintf(ftp[i][j].name, "ftp-%d", ports[i]);

pr_debug("registering helper for pf: %d port: %d\n",
ftp[i][j].tuple.src.l3num, ports[i]);
ret = nf_conntrack_helper_register(&ftp[i][j]);
if (ret) {
pr_err("failed to register helper for pf: %d port: %d\n",
ftp[i][j].tuple.src.l3num, ports[i]);
ports_c = i;
nf_conntrack_ftp_fini();
return ret;
}
}
nf_ct_helper_init(&ftp[2 * i], AF_INET, IPPROTO_TCP, "ftp",
FTP_PORT, ports[i], ports[i], &ftp_exp_policy,
0, sizeof(struct nf_ct_ftp_master), help,
nf_ct_ftp_from_nlattr, THIS_MODULE);
nf_ct_helper_init(&ftp[2 * i + 1], AF_INET6, IPPROTO_TCP, "ftp",
FTP_PORT, ports[i], ports[i], &ftp_exp_policy,
0, sizeof(struct nf_ct_ftp_master), 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");
kfree(ftp_buffer);
return ret;
}

return 0;
Expand Down
57 changes: 57 additions & 0 deletions net/netfilter/nf_conntrack_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,63 @@ 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, u32 data_len,
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->tuple.src.l3num = l3num;
helper->tuple.dst.protonum = protonum;
helper->tuple.src.u.all = htons(spec_port);
helper->expect_policy = exp_pol;
helper->expect_class_max = expect_class_max;
helper->data_len = data_len;
helper->help = help;
helper->from_nlattr = from_nlattr;
helper->me = module;

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)
{
unsigned int i;
int err = 0;

for (i = 0; i < n; i++) {
err = nf_conntrack_helper_register(&helper[i]);
if (err < 0)
goto err;
}

return err;
err:
if (i > 0)
nf_conntrack_helpers_unregister(helper, i);
return err;
}
EXPORT_SYMBOL_GPL(nf_conntrack_helpers_register);

void nf_conntrack_helpers_unregister(struct nf_conntrack_helper *helper,
unsigned int n)
{
while (n-- > 0)
nf_conntrack_helper_unregister(&helper[n]);
}
EXPORT_SYMBOL_GPL(nf_conntrack_helpers_unregister);

static struct nf_ct_ext_type helper_extend __read_mostly = {
.len = sizeof(struct nf_conn_help),
.align = __alignof__(struct nf_conn_help),
Expand Down
36 changes: 12 additions & 24 deletions net/netfilter/nf_conntrack_irc.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,38 +255,26 @@ static int __init nf_conntrack_irc_init(void)
ports[ports_c++] = IRC_PORT;

for (i = 0; i < ports_c; i++) {
irc[i].tuple.src.l3num = AF_INET;
irc[i].tuple.src.u.tcp.port = htons(ports[i]);
irc[i].tuple.dst.protonum = IPPROTO_TCP;
irc[i].expect_policy = &irc_exp_policy;
irc[i].me = THIS_MODULE;
irc[i].help = help;

if (ports[i] == IRC_PORT)
sprintf(irc[i].name, "irc");
else
sprintf(irc[i].name, "irc-%u", i);

ret = nf_conntrack_helper_register(&irc[i]);
if (ret) {
pr_err("failed to register helper for pf: %u port: %u\n",
irc[i].tuple.src.l3num, ports[i]);
ports_c = i;
nf_conntrack_irc_fini();
return ret;
}
nf_ct_helper_init(&irc[i], AF_INET, IPPROTO_TCP, "irc",
IRC_PORT, ports[i], i, &irc_exp_policy,
0, 0, help, NULL, THIS_MODULE);
}

ret = nf_conntrack_helpers_register(&irc[0], ports_c);
if (ret) {
pr_err("failed to register helpers\n");
kfree(irc_buffer);
return ret;
}

return 0;
}

/* This function is intentionally _NOT_ defined as __exit, because
* it is needed by the init function */
static void nf_conntrack_irc_fini(void)
{
int i;

for (i = 0; i < ports_c; i++)
nf_conntrack_helper_unregister(&irc[i]);
nf_conntrack_helpers_unregister(irc, ports_c);
kfree(irc_buffer);
}

Expand Down
57 changes: 20 additions & 37 deletions net/netfilter/nf_conntrack_sane.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ static int help(struct sk_buff *skb,
return ret;
}

static struct nf_conntrack_helper sane[MAX_PORTS][2] __read_mostly;
static struct nf_conntrack_helper sane[MAX_PORTS * 2] __read_mostly;

static const struct nf_conntrack_expect_policy sane_exp_policy = {
.max_expected = 1,
Expand All @@ -176,22 +176,13 @@ static const struct nf_conntrack_expect_policy sane_exp_policy = {
/* don't make this __exit, since it's called from __init ! */
static void nf_conntrack_sane_fini(void)
{
int i, j;

for (i = 0; i < ports_c; i++) {
for (j = 0; j < 2; j++) {
pr_debug("unregistering helper for pf: %d port: %d\n",
sane[i][j].tuple.src.l3num, ports[i]);
nf_conntrack_helper_unregister(&sane[i][j]);
}
}

nf_conntrack_helpers_unregister(sane, ports_c * 2);
kfree(sane_buffer);
}

static int __init nf_conntrack_sane_init(void)
{
int i, j = -1, ret = 0;
int i, ret = 0;

sane_buffer = kmalloc(65536, GFP_KERNEL);
if (!sane_buffer)
Expand All @@ -203,31 +194,23 @@ static int __init nf_conntrack_sane_init(void)
/* FIXME should be configurable whether IPv4 and IPv6 connections
are tracked or not - YK */
for (i = 0; i < ports_c; i++) {
sane[i][0].tuple.src.l3num = PF_INET;
sane[i][1].tuple.src.l3num = PF_INET6;
for (j = 0; j < 2; j++) {
sane[i][j].data_len = sizeof(struct nf_ct_sane_master);
sane[i][j].tuple.src.u.tcp.port = htons(ports[i]);
sane[i][j].tuple.dst.protonum = IPPROTO_TCP;
sane[i][j].expect_policy = &sane_exp_policy;
sane[i][j].me = THIS_MODULE;
sane[i][j].help = help;
if (ports[i] == SANE_PORT)
sprintf(sane[i][j].name, "sane");
else
sprintf(sane[i][j].name, "sane-%d", ports[i]);

pr_debug("registering helper for pf: %d port: %d\n",
sane[i][j].tuple.src.l3num, ports[i]);
ret = nf_conntrack_helper_register(&sane[i][j]);
if (ret) {
pr_err("failed to register helper for pf: %d port: %d\n",
sane[i][j].tuple.src.l3num, ports[i]);
ports_c = i;
nf_conntrack_sane_fini();
return ret;
}
}
nf_ct_helper_init(&sane[2 * i], AF_INET, IPPROTO_TCP, "sane",
SANE_PORT, ports[i], ports[i],
&sane_exp_policy, 0,
sizeof(struct nf_ct_sane_master), help, NULL,
THIS_MODULE);
nf_ct_helper_init(&sane[2 * i + 1], AF_INET6, IPPROTO_TCP, "sane",
SANE_PORT, ports[i], ports[i],
&sane_exp_policy, 0,
sizeof(struct nf_ct_sane_master), help, NULL,
THIS_MODULE);
}

ret = nf_conntrack_helpers_register(sane, ports_c * 2);
if (ret < 0) {
pr_err("failed to register helpers\n");
kfree(sane_buffer);
return ret;
}

return 0;
Expand Down
Loading

0 comments on commit 82de0be

Please sign in to comment.