From bb3127f6430ccedeb82f4ee11f11fe05d5bd390c Mon Sep 17 00:00:00 2001 From: laforge Date: Mon, 26 Aug 2002 12:21:44 +0000 Subject: fix long-standing bug with regard to protocol-on-demand-loading and iptables-save/restore (1.2.7 release bug) --- iptables.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 15 deletions(-) (limited to 'iptables.c') diff --git a/iptables.c b/iptables.c index cd3c1fe..fa570c5 100644 --- a/iptables.c +++ b/iptables.c @@ -1659,6 +1659,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) const char *jumpto = ""; char *protocol = NULL; const char *modprobe = NULL; + int proto_used = 0; memset(&fw, 0, sizeof(fw)); @@ -1686,7 +1687,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) opterr = 0; while ((c = getopt_long(argc, argv, - "-A:C:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:", + "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:", opts, NULL)) != -1) { switch (c) { /* @@ -1839,20 +1840,6 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) exit_error(PARAMETER_PROBLEM, "rule would never match protocol"); fw.nfcache |= NFC_IP_PROTO; - - /* try to load match with protocol name */ - if ((m = find_proto(protocol, TRY_LOAD, - options&OPT_NUMERIC))) { - size_t size; - size = IPT_ALIGN(sizeof(struct ipt_entry_match)) - + m->size; - m->m = fw_calloc(1, size); - m->m->u.match_size = size; - strcpy(m->m->u.user.name, m->name); - m->init(m->m, &fw.nfcache); - opts = merge_options(opts, m->extra_opts, &m->option_offset); - } - break; case 's': @@ -2038,6 +2025,59 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) &m->m)) break; } + + /* If you listen carefully, you can + actually hear this code suck. */ + + /* some explanations (after four different bugs + * in 3 different releases): If we encountere a + * parameter, that has not been parsed yet, + * it's not an option of an explicitly loaded + * match or a target. However, we support + * implicit loading of the protocol match + * extension. '-p tcp' means 'l4 proto 6' and + * at the same time 'load tcp protocol match on + * demand if we specify --dport'. + * + * To make this work, we need to make sure: + * - the parameter has not been parsed by + * a match (m above) + * - a protocol has been specified + * - the protocol extension has not been + * loaded yet, or is loaded and unused + * [think of iptables-restore!] + * - the protocol extension can be successively + * loaded + */ + if (m == NULL + && protocol + && (!find_proto(protocol, DONT_LOAD, + options&OPT_NUMERIC) + || (find_proto(protocol, DONT_LOAD, + options&OPT_NUMERIC) + && (proto_used == 0)) + ) + && (m = find_proto(protocol, TRY_LOAD, + options&OPT_NUMERIC))) { + /* Try loading protocol */ + size_t size; + + proto_used = 1; + + size = IPT_ALIGN(sizeof(struct ipt_entry_match)) + + m->size; + + m->m = fw_calloc(1, size); + m->m->u.match_size = size; + strcpy(m->m->u.user.name, m->name); + m->init(m->m, &fw.nfcache); + + opts = merge_options(opts, + m->extra_opts, &m->option_offset); + + optind--; + continue; + } if (!m) exit_error(PARAMETER_PROBLEM, "Unknown arg `%s'", -- cgit v1.2.3