summaryrefslogtreecommitdiffstats
path: root/ip6tables.c
diff options
context:
space:
mode:
authorPablo Neira <pablo@eurodev.net>2005-05-29 19:05:23 +0000
committerHarald Welte <laforge@gnumonks.org>2005-05-29 19:05:23 +0000
commitdfdcd641085d22f7f911ca431db845590493c336 (patch)
treebad7a2205c28951d22fc32834e8618f7fd6e2eb2 /ip6tables.c
parent56506a10c3bc3e13134db607fd94b4f4067426f3 (diff)
Release previously merged options from merge_opts(), reduces memory-usage of iptables-restore dramatically (Pablo Neira)
Diffstat (limited to 'ip6tables.c')
-rw-r--r--ip6tables.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/ip6tables.c b/ip6tables.c
index cea72292..11d8cd16 100644
--- a/ip6tables.c
+++ b/ip6tables.c
@@ -252,6 +252,16 @@ in6addrcpy(struct in6_addr *dst, struct in6_addr *src)
/* dst->s6_addr = src->s6_addr; */
}
+static void free_opts(int reset_offset)
+{
+ if (opts != original_opts) {
+ free(opts);
+ opts = original_opts;
+ if (reset_offset)
+ global_option_offset = 0;
+ }
+}
+
void
exit_error(enum exittype status, char *msg, ...)
{
@@ -267,6 +277,8 @@ exit_error(enum exittype status, char *msg, ...)
if (status == VERSION_PROBLEM)
fprintf(stderr,
"Perhaps ip6tables or your kernel needs to be upgraded.\n");
+ /* On error paths, make sure that we don't leak memory */
+ free_opts(1);
exit(status);
}
@@ -277,6 +289,7 @@ exit_tryhelp(int status)
fprintf(stderr, "Error occurred at line: %d\n", line);
fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
program_name, program_name );
+ free_opts(1);
exit(status);
}
@@ -1016,6 +1029,9 @@ merge_options(struct option *oldopts, const struct option *newopts,
unsigned int num_old, num_new, i;
struct option *merge;
+ /* Release previous options merged if any */
+ free_opts(0);
+
for (num_old = 0; oldopts[num_old].name; num_old++);
for (num_new = 0; newopts[num_new].name; num_new++);
@@ -2336,11 +2352,7 @@ int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
for (c = 0; c < ndaddrs; c++)
free(&daddrs[c]);
- if (opts != original_opts) {
- free(opts);
- opts = original_opts;
- global_option_offset = 0;
- }
+ free_opts(1);
return ret;
}