summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2011-02-17 19:05:32 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2011-02-17 19:05:32 +0100
commit3bb13acbff0983960e06eb33e0daa98c3dab472c (patch)
tree39f4aadef642321fe829162cb57d180b98074020 /src
parent6c4ec15505b9fe878ade0b3e7cdbc8f0a26861cd (diff)
conntrack: allocate template objects in the heap
With this patch, we don't abuse the stack anymore, instead we allocate the template objects that are used in the heap. We stop using nfct_maxsize() which is now deprecated in libnetfilter_conntrack. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/conntrack.c150
1 files changed, 89 insertions, 61 deletions
diff --git a/src/conntrack.c b/src/conntrack.c
index 9565ee4..fe4cbf0 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -58,6 +58,37 @@
#include <fcntl.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
+/* These are the template objects that are used to send commands. */
+static struct {
+ struct nf_conntrack *ct;
+ struct nf_expect *exp;
+ /* Expectations require the expectation tuple and the mask. */
+ struct nf_conntrack *exptuple, *mask;
+} tmpl;
+
+static int alloc_tmpl_objects(void)
+{
+ tmpl.ct = nfct_new();
+ tmpl.exptuple = nfct_new();
+ tmpl.mask = nfct_new();
+ tmpl.exp = nfexp_new();
+
+ return tmpl.ct != NULL && tmpl.exptuple != NULL &&
+ tmpl.mask != NULL && tmpl.exp != NULL;
+}
+
+static void free_tmpl_objects(void)
+{
+ if (tmpl.ct)
+ nfct_destroy(tmpl.ct);
+ if (tmpl.exptuple)
+ nfct_destroy(tmpl.exptuple);
+ if (tmpl.mask)
+ nfct_destroy(tmpl.mask);
+ if (tmpl.exp)
+ nfexp_destroy(tmpl.exp);
+}
+
enum ct_command {
CT_NONE = 0,
@@ -534,6 +565,8 @@ exit_error(enum exittype status, const char *msg, ...)
va_end(args);
if (status == PARAMETER_PROBLEM)
exit_tryhelp(status);
+ /* release template objects that were allocated in the setup stage. */
+ free_tmpl_objects();
exit(status);
}
@@ -850,12 +883,12 @@ nat_parse(char *arg, struct nf_conntrack *obj, int type)
"Invalid port:port syntax");
if (type == CT_OPT_SRC_NAT)
- nfct_set_attr_u16(obj, ATTR_SNAT_PORT, ntohs(port));
+ nfct_set_attr_u16(tmpl.ct, ATTR_SNAT_PORT, ntohs(port));
else if (type == CT_OPT_DST_NAT)
- nfct_set_attr_u16(obj, ATTR_DNAT_PORT, ntohs(port));
+ nfct_set_attr_u16(tmpl.ct, ATTR_DNAT_PORT, ntohs(port));
else if (type == CT_OPT_ANY_NAT) {
- nfct_set_attr_u16(obj, ATTR_SNAT_PORT, ntohs(port));
- nfct_set_attr_u16(obj, ATTR_DNAT_PORT, ntohs(port));
+ nfct_set_attr_u16(tmpl.ct, ATTR_SNAT_PORT, ntohs(port));
+ nfct_set_attr_u16(tmpl.ct, ATTR_DNAT_PORT, ntohs(port));
}
}
@@ -869,9 +902,9 @@ nat_parse(char *arg, struct nf_conntrack *obj, int type)
}
if (type == CT_OPT_SRC_NAT || type == CT_OPT_ANY_NAT)
- nfct_set_attr_u32(obj, ATTR_SNAT_IPV4, parse.v4);
+ nfct_set_attr_u32(tmpl.ct, ATTR_SNAT_IPV4, parse.v4);
else if (type == CT_OPT_DST_NAT || type == CT_OPT_ANY_NAT)
- nfct_set_attr_u32(obj, ATTR_DNAT_IPV4, parse.v4);
+ nfct_set_attr_u32(tmpl.ct, ATTR_DNAT_IPV4, parse.v4);
}
static void
@@ -1143,11 +1176,7 @@ static int update_cb(enum nf_conntrack_msg_type type,
void *data)
{
int res;
- struct nf_conntrack *obj = data;
- char __tmp[nfct_maxsize()];
- struct nf_conntrack *tmp = (struct nf_conntrack *) (void *)__tmp;
-
- memset(tmp, 0, sizeof(__tmp));
+ struct nf_conntrack *obj = data, *tmp;
if (filter_nat(obj, ct))
return NFCT_CB_CONTINUE;
@@ -1161,30 +1190,35 @@ static int update_cb(enum nf_conntrack_msg_type type,
if (options & CT_OPT_TUPLE_REPL && !nfct_cmp(obj, ct, NFCT_CMP_REPL))
return NFCT_CB_CONTINUE;
+ tmp = nfct_new();
+ if (tmp == NULL)
+ exit_error(OTHER_PROBLEM, "out of memory");
+
nfct_copy(tmp, ct, NFCT_CP_ORIG);
nfct_copy(tmp, obj, NFCT_CP_META);
res = nfct_query(ith, NFCT_Q_UPDATE, tmp);
- if (res < 0)
+ if (res < 0) {
+ nfct_destroy(tmp);
exit_error(OTHER_PROBLEM,
"Operation failed: %s",
err2str(errno, CT_UPDATE));
-
+ }
nfct_callback_register(ith, NFCT_T_ALL, print_cb, NULL);
res = nfct_query(ith, NFCT_Q_GET, tmp);
if (res < 0) {
+ nfct_destroy(tmp);
/* the entry has vanish in middle of the update */
if (errno == ENOENT) {
nfct_callback_unregister(ith);
return NFCT_CB_CONTINUE;
}
-
exit_error(OTHER_PROBLEM,
"Operation failed: %s",
err2str(errno, CT_UPDATE));
}
-
+ nfct_destroy(tmp);
nfct_callback_unregister(ith);
counter++;
@@ -1303,23 +1337,13 @@ int main(int argc, char *argv[])
int res = 0, partial;
size_t socketbuffersize = 0;
int family = AF_UNSPEC;
- char __obj[nfct_maxsize()];
- char __exptuple[nfct_maxsize()];
- char __mask[nfct_maxsize()];
- struct nf_conntrack *obj = (struct nf_conntrack *)(void*) __obj;
- struct nf_conntrack *exptuple =
- (struct nf_conntrack *)(void*) __exptuple;
- struct nf_conntrack *mask = (struct nf_conntrack *)(void*) __mask;
- char __exp[nfexp_maxsize()];
- struct nf_expect *exp = (struct nf_expect *)(void*) __exp;
int l3protonum, protonum = 0;
union ct_address ad;
unsigned int command = 0;
- memset(__obj, 0, sizeof(__obj));
- memset(__exptuple, 0, sizeof(__exptuple));
- memset(__mask, 0, sizeof(__mask));
- memset(__exp, 0, sizeof(__exp));
+ /* we release these objects in the exit_error() path. */
+ if (!alloc_tmpl_objects())
+ exit_error(OTHER_PROBLEM, "out of memory");
register_tcp();
register_udp();
@@ -1374,15 +1398,15 @@ int main(int argc, char *argv[])
}
set_family(&family, l3protonum);
if (l3protonum == AF_INET) {
- nfct_set_attr_u32(obj,
+ nfct_set_attr_u32(tmpl.ct,
opt2family_attr[c][0],
ad.v4);
} else if (l3protonum == AF_INET6) {
- nfct_set_attr(obj,
+ nfct_set_attr(tmpl.ct,
opt2family_attr[c][1],
&ad.v6);
}
- nfct_set_attr_u8(obj, opt2attr[c], l3protonum);
+ nfct_set_attr_u8(tmpl.ct, opt2attr[c], l3protonum);
break;
case '{':
case '}':
@@ -1396,15 +1420,16 @@ int main(int argc, char *argv[])
}
set_family(&family, l3protonum);
if (l3protonum == AF_INET) {
- nfct_set_attr_u32(mask,
+ nfct_set_attr_u32(tmpl.mask,
opt2family_attr[c][0],
ad.v4);
} else if (l3protonum == AF_INET6) {
- nfct_set_attr(mask,
+ nfct_set_attr(tmpl.mask,
opt2family_attr[c][1],
&ad.v6);
}
- nfct_set_attr_u8(mask, ATTR_ORIG_L3PROTO, l3protonum);
+ nfct_set_attr_u8(tmpl.mask,
+ ATTR_ORIG_L3PROTO, l3protonum);
break;
case 'p':
options |= CT_OPT_PROTO;
@@ -1418,17 +1443,18 @@ int main(int argc, char *argv[])
if (opts == NULL)
exit_error(OTHER_PROBLEM, "out of memory");
- nfct_set_attr_u8(obj, ATTR_L4PROTO, protonum);
+ nfct_set_attr_u8(tmpl.ct, ATTR_L4PROTO, protonum);
break;
case 't':
options |= CT_OPT_TIMEOUT;
- nfct_set_attr_u32(obj, ATTR_TIMEOUT, atol(optarg));
- nfexp_set_attr_u32(exp, ATTR_EXP_TIMEOUT, atol(optarg));
+ nfct_set_attr_u32(tmpl.ct, ATTR_TIMEOUT, atol(optarg));
+ nfexp_set_attr_u32(tmpl.exp,
+ ATTR_EXP_TIMEOUT, atol(optarg));
break;
case 'u':
options |= CT_OPT_STATUS;
parse_parameter(optarg, &status, PARSE_STATUS);
- nfct_set_attr_u32(obj, ATTR_STATUS, status);
+ nfct_set_attr_u32(tmpl.ct, ATTR_STATUS, status);
break;
case 'e':
options |= CT_OPT_EVENT_MASK;
@@ -1458,12 +1484,12 @@ int main(int argc, char *argv[])
continue;
set_family(&family, AF_INET);
- nat_parse(tmp, obj, opt2type[c]);
+ nat_parse(tmp, tmpl.ct, opt2type[c]);
break;
}
case 'w':
options |= opt2type[c];
- nfct_set_attr_u16(obj,
+ nfct_set_attr_u16(tmpl.ct,
opt2attr[c],
strtoul(optarg, NULL, 0));
break;
@@ -1471,7 +1497,7 @@ int main(int argc, char *argv[])
case 'm':
case 'c':
options |= opt2type[c];
- nfct_set_attr_u32(obj,
+ nfct_set_attr_u32(tmpl.ct,
opt2attr[c],
strtoul(optarg, NULL, 0));
break;
@@ -1506,8 +1532,9 @@ int main(int argc, char *argv[])
break;
default:
if (h && h->parse_opts
- &&!h->parse_opts(c - h->option_offset, obj,
- exptuple, mask, &l4flags))
+ &&!h->parse_opts(c - h->option_offset, tmpl.ct,
+ tmpl.exptuple, tmpl.mask,
+ &l4flags))
exit_error(PARAMETER_PROBLEM, "parse error");
break;
}
@@ -1543,7 +1570,7 @@ int main(int argc, char *argv[])
}
}
if (!(command & CT_HELP) && h && h->final_check)
- h->final_check(l4flags, cmd, obj);
+ h->final_check(l4flags, cmd, tmpl.ct);
switch(command) {
@@ -1557,7 +1584,7 @@ int main(int argc, char *argv[])
exit_error(PARAMETER_PROBLEM, "Can't use -z with "
"filtering parameters");
- nfct_callback_register(cth, NFCT_T_ALL, dump_cb, obj);
+ nfct_callback_register(cth, NFCT_T_ALL, dump_cb, tmpl.ct);
if (options & CT_OPT_ZERO)
res = nfct_query(cth, NFCT_Q_DUMP_RESET, &family);
@@ -1584,30 +1611,30 @@ int main(int argc, char *argv[])
case CT_CREATE:
if ((options & CT_OPT_ORIG) && !(options & CT_OPT_REPL))
- nfct_setobjopt(obj, NFCT_SOPT_SETUP_REPLY);
+ nfct_setobjopt(tmpl.ct, NFCT_SOPT_SETUP_REPLY);
else if (!(options & CT_OPT_ORIG) && (options & CT_OPT_REPL))
- nfct_setobjopt(obj, NFCT_SOPT_SETUP_ORIGINAL);
+ nfct_setobjopt(tmpl.ct, NFCT_SOPT_SETUP_ORIGINAL);
cth = nfct_open(CONNTRACK, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- res = nfct_query(cth, NFCT_Q_CREATE, obj);
+ res = nfct_query(cth, NFCT_Q_CREATE, tmpl.ct);
if (res != -1)
counter++;
nfct_close(cth);
break;
case EXP_CREATE:
- nfexp_set_attr(exp, ATTR_EXP_MASTER, obj);
- nfexp_set_attr(exp, ATTR_EXP_EXPECTED, exptuple);
- nfexp_set_attr(exp, ATTR_EXP_MASK, mask);
+ nfexp_set_attr(tmpl.exp, ATTR_EXP_MASTER, tmpl.ct);
+ nfexp_set_attr(tmpl.exp, ATTR_EXP_EXPECTED, tmpl.exptuple);
+ nfexp_set_attr(tmpl.exp, ATTR_EXP_MASK, tmpl.mask);
cth = nfct_open(EXPECT, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- res = nfexp_query(cth, NFCT_Q_CREATE, exp);
+ res = nfexp_query(cth, NFCT_Q_CREATE, tmpl.exp);
nfct_close(cth);
break;
@@ -1618,7 +1645,7 @@ int main(int argc, char *argv[])
if (!cth || !ith)
exit_error(OTHER_PROBLEM, "Can't open handler");
- nfct_callback_register(cth, NFCT_T_ALL, update_cb, obj);
+ nfct_callback_register(cth, NFCT_T_ALL, update_cb, tmpl.ct);
res = nfct_query(cth, NFCT_Q_DUMP, &family);
nfct_close(ith);
@@ -1631,7 +1658,7 @@ int main(int argc, char *argv[])
if (!cth || !ith)
exit_error(OTHER_PROBLEM, "Can't open handler");
- nfct_callback_register(cth, NFCT_T_ALL, delete_cb, obj);
+ nfct_callback_register(cth, NFCT_T_ALL, delete_cb, tmpl.ct);
res = nfct_query(cth, NFCT_Q_DUMP, &family);
nfct_close(ith);
@@ -1639,13 +1666,13 @@ int main(int argc, char *argv[])
break;
case EXP_DELETE:
- nfexp_set_attr(exp, ATTR_EXP_EXPECTED, obj);
+ nfexp_set_attr(tmpl.exp, ATTR_EXP_EXPECTED, tmpl.ct);
cth = nfct_open(EXPECT, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- res = nfexp_query(cth, NFCT_Q_DESTROY, exp);
+ res = nfexp_query(cth, NFCT_Q_DESTROY, tmpl.exp);
nfct_close(cth);
break;
@@ -1654,20 +1681,20 @@ int main(int argc, char *argv[])
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
- nfct_callback_register(cth, NFCT_T_ALL, dump_cb, obj);
- res = nfct_query(cth, NFCT_Q_GET, obj);
+ nfct_callback_register(cth, NFCT_T_ALL, dump_cb, tmpl.ct);
+ res = nfct_query(cth, NFCT_Q_GET, tmpl.ct);
nfct_close(cth);
break;
case EXP_GET:
- nfexp_set_attr(exp, ATTR_EXP_MASTER, obj);
+ nfexp_set_attr(tmpl.exp, ATTR_EXP_MASTER, tmpl.ct);
cth = nfct_open(EXPECT, 0);
if (!cth)
exit_error(OTHER_PROBLEM, "Can't open handler");
nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, NULL);
- res = nfexp_query(cth, NFCT_Q_GET, exp);
+ res = nfexp_query(cth, NFCT_Q_GET, tmpl.exp);
nfct_close(cth);
break;
@@ -1719,7 +1746,7 @@ int main(int argc, char *argv[])
}
signal(SIGINT, event_sighandler);
signal(SIGTERM, event_sighandler);
- nfct_callback_register(cth, NFCT_T_ALL, event_cb, obj);
+ nfct_callback_register(cth, NFCT_T_ALL, event_cb, tmpl.ct);
res = nfct_catch(cth);
if (res == -1) {
if (errno == ENOBUFS) {
@@ -1810,6 +1837,7 @@ int main(int argc, char *argv[])
exit_error(OTHER_PROBLEM, "Operation failed: %s",
err2str(errno, command));
+ free_tmpl_objects();
free_options();
if (command && exit_msg[cmd][0]) {