From 78cafdaf474a333fa39efab4aa4c9aed88ab9518 Mon Sep 17 00:00:00 2001 From: Martin Josefsson Date: Mon, 2 Feb 2004 20:01:18 +0000 Subject: Make sure to use matches in the order they are given when calling do_command() multiple times. --- iptables.c | 129 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 67 insertions(+), 62 deletions(-) (limited to 'iptables.c') diff --git a/iptables.c b/iptables.c index c438d604..2c6282a5 100644 --- a/iptables.c +++ b/iptables.c @@ -661,7 +661,7 @@ parse_hostnetworkmask(const char *name, struct in_addr **addrpp, } struct iptables_match * -find_match(const char *name, enum ipt_tryload tryload) +find_match(const char *name, enum ipt_tryload tryload, struct iptables_rule_match **matches) { struct iptables_match *ptr; @@ -678,7 +678,7 @@ find_match(const char *name, enum ipt_tryload tryload) if (dlopen(path, RTLD_NOW)) { /* Found library. If it didn't register itself, maybe they specified target as match. */ - ptr = find_match(name, DONT_LOAD); + ptr = find_match(name, DONT_LOAD, NULL); if (!ptr) exit_error(PARAMETER_PROBLEM, @@ -702,15 +702,24 @@ find_match(const char *name, enum ipt_tryload tryload) } #endif - if (ptr) - ptr->used = 1; + if (ptr && matches) { + struct iptables_rule_match **i; + struct iptables_rule_match *newentry; + + newentry = fw_malloc(sizeof(struct iptables_rule_match)); + + for (i = matches; *i; i = &(*i)->next); + newentry->match = ptr; + newentry->next = NULL; + *i = newentry; + } return ptr; } /* Christophe Burki wants `-p 6' to imply `-m tcp'. */ static struct iptables_match * -find_proto(const char *pname, enum ipt_tryload tryload, int nolookup) +find_proto(const char *pname, enum ipt_tryload tryload, int nolookup, struct iptables_rule_match **matches) { unsigned int proto; @@ -718,9 +727,9 @@ find_proto(const char *pname, enum ipt_tryload tryload, int nolookup) char *protoname = proto_to_name(proto, nolookup); if (protoname) - return find_match(protoname, tryload); + return find_match(protoname, tryload, matches); } else - return find_match(pname, tryload); + return find_match(pname, tryload, matches); return NULL; } @@ -1018,7 +1027,7 @@ register_match(struct iptables_match *me) exit(1); } - if (find_match(me->name, DONT_LOAD)) { + if (find_match(me->name, DONT_LOAD, NULL)) { fprintf(stderr, "%s: match `%s' already registered.\n", program_name, me->name); exit(1); @@ -1148,7 +1157,7 @@ print_match(const struct ipt_entry_match *m, const struct ipt_ip *ip, int numeric) { - struct iptables_match *match = find_match(m->u.user.name, TRY_LOAD); + struct iptables_match *match = find_match(m->u.user.name, TRY_LOAD, NULL); if (match) { if (match->print) @@ -1364,20 +1373,16 @@ insert_entry(const ipt_chainlabel chain, } static unsigned char * -make_delete_mask(struct ipt_entry *fw) +make_delete_mask(struct ipt_entry *fw, struct iptables_rule_match *matches) { /* Establish mask for comparison */ unsigned int size; - struct iptables_match *m; + struct iptables_rule_match *matchp; unsigned char *mask, *mptr; size = sizeof(struct ipt_entry); - for (m = iptables_matches; m; m = m->next) { - if (!m->used) - continue; - - size += IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size; - } + for (matchp = matches; matchp; matchp = matchp->next) + size += IPT_ALIGN(sizeof(struct ipt_entry_match)) + matchp->match->size; mask = fw_calloc(1, size + IPT_ALIGN(sizeof(struct ipt_entry_target)) @@ -1386,14 +1391,11 @@ make_delete_mask(struct ipt_entry *fw) memset(mask, 0xFF, sizeof(struct ipt_entry)); mptr = mask + sizeof(struct ipt_entry); - for (m = iptables_matches; m; m = m->next) { - if (!m->used) - continue; - + for (matchp = matches; matchp; matchp = matchp->next) { memset(mptr, 0xFF, IPT_ALIGN(sizeof(struct ipt_entry_match)) - + m->userspacesize); - mptr += IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size; + + matchp->match->userspacesize); + mptr += IPT_ALIGN(sizeof(struct ipt_entry_match)) + matchp->match->size; } memset(mptr, 0xFF, @@ -1411,13 +1413,14 @@ delete_entry(const ipt_chainlabel chain, unsigned int ndaddrs, const struct in_addr daddrs[], int verbose, - iptc_handle_t *handle) + iptc_handle_t *handle, + struct iptables_rule_match *matches) { unsigned int i, j; int ret = 1; unsigned char *mask; - mask = make_delete_mask(fw); + mask = make_delete_mask(fw, matches); for (i = 0; i < nsaddrs; i++) { fw->ip.src.s_addr = saddrs[i].s_addr; for (j = 0; j < ndaddrs; j++) { @@ -1616,20 +1619,16 @@ int iptables_insmod(const char *modname, const char *modprobe) static struct ipt_entry * generate_entry(const struct ipt_entry *fw, - struct iptables_match *matches, + struct iptables_rule_match *matches, struct ipt_entry_target *target) { unsigned int size; - struct iptables_match *m; + struct iptables_rule_match *matchp; struct ipt_entry *e; size = sizeof(struct ipt_entry); - for (m = matches; m; m = m->next) { - if (!m->used) - continue; - - size += m->m->u.match_size; - } + for (matchp = matches; matchp; matchp = matchp->next) + size += matchp->match->m->u.match_size; e = fw_malloc(size + target->u.target_size); *e = *fw; @@ -1637,18 +1636,28 @@ generate_entry(const struct ipt_entry *fw, e->next_offset = size + target->u.target_size; size = 0; - for (m = matches; m; m = m->next) { - if (!m->used) - continue; - - memcpy(e->elems + size, m->m, m->m->u.match_size); - size += m->m->u.match_size; + for (matchp = matches; matchp; matchp = matchp->next) { + memcpy(e->elems + size, matchp->match->m, matchp->match->m->u.match_size); + size += matchp->match->m->u.match_size; } memcpy(e->elems + size, target, target->u.target_size); return e; } +void clear_rule_matches(struct iptables_rule_match **matches) +{ + struct iptables_rule_match *matchp, *tmp; + + for (matchp = *matches; matchp;) { + tmp = matchp->next; + free(matchp); + matchp = tmp; + } + + *matches = NULL; +} + int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) { struct ipt_entry fw, *e = NULL; @@ -1664,6 +1673,8 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) const char *pcnt = NULL, *bcnt = NULL; int ret = 1; struct iptables_match *m; + struct iptables_rule_match *matches = NULL; + struct iptables_rule_match *matchp; struct iptables_target *target = NULL; struct iptables_target *t; const char *jumpto = ""; @@ -1682,10 +1693,8 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) /* clear mflags in case do_command gets called a second time * (we clear the global list of all matches for security)*/ - for (m = iptables_matches; m; m = m->next) { + for (m = iptables_matches; m; m = m->next) m->mflags = 0; - m->used = 0; - } for (t = iptables_targets; t; t = t->next) { t->tflags = 0; @@ -1826,7 +1835,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) /* iptables -p icmp -h */ if (!iptables_matches && protocol) - find_match(protocol, TRY_LOAD); + find_match(protocol, TRY_LOAD, NULL); exit_printhelp(); @@ -1931,7 +1940,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) exit_error(PARAMETER_PROBLEM, "unexpected ! flag before --match"); - m = find_match(optarg, LOAD_MUST_SUCCEED); + m = find_match(optarg, LOAD_MUST_SUCCEED, &matches); size = IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size; m->m = fw_calloc(1, size); @@ -2023,18 +2032,16 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) argv, invert, &target->tflags, &fw, &target->t))) { - for (m = iptables_matches; m; m = m->next) { - if (!m->used) - continue; - - if (m->parse(c - m->option_offset, + for (matchp = matches; matchp; matchp = matchp->next) { + if (matchp->match->parse(c - matchp->match->option_offset, argv, invert, - &m->mflags, + &matchp->match->mflags, &fw, &fw.nfcache, - &m->m)) + &matchp->match->m)) break; } + m = matchp ? matchp->match : NULL; /* If you listen carefully, you can actually hear this code suck. */ @@ -2062,13 +2069,13 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) if (m == NULL && protocol && (!find_proto(protocol, DONT_LOAD, - options&OPT_NUMERIC) + options&OPT_NUMERIC, NULL) || (find_proto(protocol, DONT_LOAD, - options&OPT_NUMERIC) + options&OPT_NUMERIC, NULL) && (proto_used == 0)) ) && (m = find_proto(protocol, TRY_LOAD, - options&OPT_NUMERIC))) { + options&OPT_NUMERIC, &matches))) { /* Try loading protocol */ size_t size; @@ -2097,12 +2104,8 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) invert = FALSE; } - for (m = iptables_matches; m; m = m->next) { - if (!m->used) - continue; - - m->final_check(m->mflags); - } + for (matchp = matches; matchp; matchp = matchp->next) + matchp->match->final_check(matchp->match->mflags); if (target) target->final_check(target->tflags); @@ -2220,7 +2223,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) * chain. */ find_target(jumpto, LOAD_MUST_SUCCEED); } else { - e = generate_entry(&fw, iptables_matches, target->t); + e = generate_entry(&fw, matches, target->t); } } @@ -2235,7 +2238,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) ret = delete_entry(chain, e, nsaddrs, saddrs, ndaddrs, daddrs, options&OPT_VERBOSE, - handle); + handle, matches); break; case CMD_DELETE_NUM: ret = iptc_delete_num_entry(chain, rulenum - 1, handle); @@ -2296,5 +2299,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) if (verbose > 1) dump_entries(*handle); + clear_rule_matches(&matches); + return ret; } -- cgit v1.2.3