#define FALSE 0
#endif
-#ifndef IPT_LIB_DIR
-#define IPT_LIB_DIR "/usr/lib/iptables"
-#endif
-
#ifndef PROC_SYS_MODPROBE
#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
#endif
#define OPT_COUNTERS 0x00800U
#define NUMBER_OF_OPT 12
static const char optflags[NUMBER_OF_OPT]
-= { 'n', 's', 'd', 'p', 'j', 'v', 'x', 'i', 'o', 'f', '3', 'c'};
+= { 'n', 's', 'd', 'p', 'j', 'v', 'x', 'i', 'o', 'f', '0', 'c'};
static struct option original_opts[] = {
{ "append", 1, 0, 'A' },
* magic number of -1 */
int line = -1;
-#ifndef __OPTIMIZE__
-struct ipt_entry_target *
-ipt_get_target(struct ipt_entry *e)
-{
- return (void *)e + e->target_offset;
-}
-#endif
-
static struct option *opts = original_opts;
static unsigned int global_option_offset = 0;
const char *program_version;
const char *program_name;
+char *lib_dir;
/* Keeping track of external matches and targets: linked lists. */
struct iptables_match *iptables_matches = NULL;
{ "icmp", IPPROTO_ICMP },
{ "esp", IPPROTO_ESP },
{ "ah", IPPROTO_AH },
+ { "sctp", IPPROTO_SCTP },
{ "all", 0 },
};
/* copy dotted string, because we need to modify it */
strncpy(buf, dotted, sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = '\0';
addrp = (unsigned char *) &(addr.s_addr);
p = buf;
dst->s_addr = src->s_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, ...)
{
if (status == VERSION_PROBLEM)
fprintf(stderr,
"Perhaps iptables or your kernel needs to be upgraded.\n");
+ /* On error paths, make sure that we don't leak memory */
+ free_opts(1);
exit(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);
}
void
-exit_printhelp(void)
+exit_printhelp(struct iptables_rule_match *matches)
{
- struct iptables_match *m = NULL;
+ struct iptables_rule_match *matchp = NULL;
struct iptables_target *t = NULL;
printf("%s v%s\n\n"
/* Print out any special helps. A user might like to be able
to add a --help to the commandline, and see expected
- results. So we call help for all matches & targets */
- for (t=iptables_targets;t;t=t->next) {
- printf("\n");
- t->help();
+ results. So we call help for all specified matches & targets */
+ for (t = iptables_targets; t ;t = t->next) {
+ if (t->used) {
+ printf("\n");
+ t->help();
+ }
}
- for (m=iptables_matches;m;m=m->next) {
+ for (matchp = matches; matchp; matchp = matchp->next) {
printf("\n");
- m->help();
+ matchp->match->help();
}
exit(0);
}
while (host->h_addr_list[*naddr] != (char *) NULL)
(*naddr)++;
- addr = fw_calloc(*naddr, sizeof(struct in_addr));
+ addr = fw_calloc(*naddr, sizeof(struct in_addr) * *naddr);
for (i = 0; i < *naddr; i++)
inaddrcpy(&(addr[i]),
(struct in_addr *) host->h_addr_list[i]);
int i, j, k, n;
strncpy(buf, name, sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = '\0';
if ((p = strrchr(buf, '/')) != NULL) {
*p = '\0';
addrp = parse_mask(p + 1);
}
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;
#ifndef NO_SHARED_LIBS
if (!ptr && tryload != DONT_LOAD) {
- char path[sizeof(IPT_LIB_DIR) + sizeof("/libipt_.so")
+ char path[strlen(lib_dir) + sizeof("/libipt_.so")
+ strlen(name)];
- sprintf(path, IPT_LIB_DIR "/libipt_%s.so", name);
+ sprintf(path, "%s/libipt_%s.so", lib_dir, name);
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,
}
#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;
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;
}
return (u_int16_t)proto;
}
-static void
-parse_interface(const char *arg, char *vianame, unsigned char *mask)
+void parse_interface(const char *arg, char *vianame, unsigned char *mask)
{
int vialen = strlen(arg);
unsigned int i;
" (%i)", arg, IFNAMSIZ-1);
strcpy(vianame, arg);
- if (vialen == 0)
+ if ((vialen == 0) || (vialen == 1 && vianame[0] == '+'))
memset(mask, 0, IFNAMSIZ);
else if (vianame[vialen - 1] == '+') {
memset(mask, 0xFF, vialen - 1);
if (strlen(targetname)+1 > sizeof(ipt_chainlabel))
exit_error(PARAMETER_PROBLEM,
- "Invalid target name `%s' (%i chars max)",
- targetname, sizeof(ipt_chainlabel)-1);
+ "Invalid target name `%s' (%u chars max)",
+ targetname, (unsigned int)sizeof(ipt_chainlabel)-1);
for (ptr = targetname; *ptr; ptr++)
if (isspace(*ptr))
}
int
-string_to_number(const char *s, unsigned int min, unsigned int max,
- unsigned int *ret)
+string_to_number_ll(const char *s, unsigned long long min, unsigned long long max,
+ unsigned long long *ret)
{
- long number;
+ unsigned long long number;
char *end;
/* Handle hex, octal, etc. */
errno = 0;
- number = strtol(s, &end, 0);
+ number = strtoull(s, &end, 0);
if (*end == '\0' && end != s) {
/* we parsed a number, let's see if we want this */
- if (errno != ERANGE && min <= number && number <= max) {
+ if (errno != ERANGE && min <= number && (!max || number <= max)) {
*ret = number;
return 0;
}
return -1;
}
+int
+string_to_number_l(const char *s, unsigned long min, unsigned long max,
+ unsigned long *ret)
+{
+ int result;
+ unsigned long long number;
+
+ result = string_to_number_ll(s, min, max, &number);
+ *ret = (unsigned long)number;
+
+ return result;
+}
+
+int string_to_number(const char *s, unsigned int min, unsigned int max,
+ unsigned int *ret)
+{
+ int result;
+ unsigned long number;
+
+ result = string_to_number_l(s, min, max, &number);
+ *ret = (unsigned int)number;
+
+ return result;
+}
+
static void
set_option(unsigned int *options, unsigned int option, u_int8_t *invflg,
int invert)
#ifndef NO_SHARED_LIBS
if (!ptr && tryload != DONT_LOAD) {
- char path[sizeof(IPT_LIB_DIR) + sizeof("/libipt_.so")
+ char path[strlen(lib_dir) + sizeof("/libipt_.so")
+ strlen(name)];
- sprintf(path, IPT_LIB_DIR "/libipt_%s.so", name);
+ sprintf(path, "%s/libipt_%s.so", lib_dir, name);
if (dlopen(path, RTLD_NOW)) {
/* Found library. If it didn't register itself,
maybe they specified match as a target. */
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++);
return merge;
}
+static int compatible_revision(const char *name, u_int8_t revision, int opt)
+{
+ struct ipt_get_revision rev;
+ socklen_t s = sizeof(rev);
+ int max_rev, sockfd;
+
+ sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+ if (sockfd < 0) {
+ fprintf(stderr, "Could not open socket to kernel: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ strcpy(rev.name, name);
+ rev.revision = revision;
+
+ max_rev = getsockopt(sockfd, IPPROTO_IP, opt, &rev, &s);
+ if (max_rev < 0) {
+ /* Definitely don't support this? */
+ if (errno == EPROTONOSUPPORT) {
+ close(sockfd);
+ return 0;
+ } else if (errno == ENOPROTOOPT) {
+ close(sockfd);
+ /* Assume only revision 0 support (old kernel) */
+ return (revision == 0);
+ } else {
+ fprintf(stderr, "getsockopt failed strangely: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ }
+ close(sockfd);
+ return 1;
+}
+
+static int compatible_match_revision(const char *name, u_int8_t revision)
+{
+ return compatible_revision(name, revision, IPT_SO_GET_REVISION_MATCH);
+}
+
+static int compatible_target_revision(const char *name, u_int8_t revision)
+{
+ return compatible_revision(name, revision, IPT_SO_GET_REVISION_TARGET);
+}
+
void
register_match(struct iptables_match *me)
{
- struct iptables_match **i;
+ struct iptables_match **i, *old;
if (strcmp(me->version, program_version) != 0) {
fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
exit(1);
}
- if (find_match(me->name, DONT_LOAD)) {
- fprintf(stderr, "%s: match `%s' already registered.\n",
+ /* Revision field stole a char from name. */
+ if (strlen(me->name) >= IPT_FUNCTION_MAXNAMELEN-1) {
+ fprintf(stderr, "%s: target `%s' has invalid name\n",
program_name, me->name);
exit(1);
}
+ old = find_match(me->name, DONT_LOAD, NULL);
+ if (old) {
+ if (old->revision == me->revision) {
+ fprintf(stderr,
+ "%s: match `%s' already registered.\n",
+ program_name, me->name);
+ exit(1);
+ }
+
+ /* Now we have two (or more) options, check compatibility. */
+ if (compatible_match_revision(old->name, old->revision)
+ && old->revision > me->revision)
+ return;
+
+ /* Replace if compatible. */
+ if (!compatible_match_revision(me->name, me->revision))
+ return;
+
+ /* Delete old one. */
+ for (i = &iptables_matches; *i!=old; i = &(*i)->next);
+ *i = old->next;
+ }
+
if (me->size != IPT_ALIGN(me->size)) {
fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
- program_name, me->name, me->size);
+ program_name, me->name, (unsigned int)me->size);
exit(1);
}
void
register_target(struct iptables_target *me)
{
+ struct iptables_target *old;
+
if (strcmp(me->version, program_version) != 0) {
fprintf(stderr, "%s: target `%s' v%s (I'm v%s).\n",
program_name, me->name, me->version, program_version);
exit(1);
}
- if (find_target(me->name, DONT_LOAD)) {
- fprintf(stderr, "%s: target `%s' already registered.\n",
+ /* Revision field stole a char from name. */
+ if (strlen(me->name) >= IPT_FUNCTION_MAXNAMELEN-1) {
+ fprintf(stderr, "%s: target `%s' has invalid name\n",
program_name, me->name);
exit(1);
}
+ old = find_target(me->name, DONT_LOAD);
+ if (old) {
+ struct iptables_target **i;
+
+ if (old->revision == me->revision) {
+ fprintf(stderr,
+ "%s: target `%s' already registered.\n",
+ program_name, me->name);
+ exit(1);
+ }
+
+ /* Now we have two (or more) options, check compatibility. */
+ if (compatible_target_revision(old->name, old->revision)
+ && old->revision > me->revision)
+ return;
+
+ /* Replace if compatible. */
+ if (!compatible_target_revision(me->name, me->revision))
+ return;
+
+ /* Delete old one. */
+ for (i = &iptables_targets; *i!=old; i = &(*i)->next);
+ *i = old->next;
+ }
+
if (me->size != IPT_ALIGN(me->size)) {
fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
- program_name, me->name, me->size);
+ program_name, me->name, (unsigned int)me->size);
exit(1);
}
number = (number + 500) / 1000;
if (number > 9999) {
number = (number + 500) / 1000;
- printf(FMT("%4lluT ","%lluT "), number);
+ printf(FMT("%4lluT ","%lluT "), (unsigned long long)number);
}
- else printf(FMT("%4lluG ","%lluG "), number);
+ else printf(FMT("%4lluG ","%lluG "), (unsigned long long)number);
}
- else printf(FMT("%4lluM ","%lluM "), number);
+ else printf(FMT("%4lluM ","%lluM "), (unsigned long long)number);
} else
- printf(FMT("%4lluK ","%lluK "), number);
+ printf(FMT("%4lluK ","%lluK "), (unsigned long long)number);
} else
- printf(FMT("%5llu ","%llu "), number);
+ printf(FMT("%5llu ","%llu "), (unsigned long long)number);
} else
- printf(FMT("%8llu ","%llu "), number);
+ printf(FMT("%8llu ","%llu "), (unsigned long long)number);
}
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)
target->print(&fw->ip, t, format & FMT_NUMERIC);
} else if (t->u.target_size != sizeof(*t))
printf("[%u bytes of unknown target data] ",
- t->u.target_size - sizeof(*t));
+ (unsigned int)(t->u.target_size - sizeof(*t)));
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
}
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))
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,
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++) {
ret &= iptc_delete_entry(chain, fw, mask, handle);
}
}
+ free(mask);
+
return ret;
}
for (i = 0; i < chaincount; i++) {
if (!builtinstoo
&& iptc_builtin(chains + i*sizeof(ipt_chainlabel),
- *handle))
+ *handle) == 1)
continue;
ret &= fn(chains + i*sizeof(ipt_chainlabel), verbose, handle);
}
int procfile;
char *ret;
+#define PROCFILE_BUFSIZ 1024
procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
if (procfile < 0)
return NULL;
- ret = malloc(1024);
+ ret = (char *) malloc(PROCFILE_BUFSIZ);
if (ret) {
- switch (read(procfile, ret, 1024)) {
+ memset(ret, 0, PROCFILE_BUFSIZ);
+ switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
case -1: goto fail;
- case 1024: goto fail; /* Partial read. Wierd */
+ case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */
}
if (ret[strlen(ret)-1]=='\n')
ret[strlen(ret)-1]=0;
{
char *buf = NULL;
char *argv[3];
- int i=0;
+ int status;
/* If they don't explicitly set it, read out of kernel */
if (!modprobe) {
switch (fork()) {
case 0:
- /* close open file descriptors */
- for (i=0; i< 10; i++) {
- close(i);
- }
argv[0] = (char *)modprobe;
argv[1] = (char *)modname;
argv[2] = NULL;
execv(argv[0], argv);
/* not usually reached */
- exit(0);
+ exit(1);
case -1:
return -1;
default: /* parent */
- wait(NULL);
+ wait(&status);
}
free(buf);
- return 0;
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
+ return 0;
+ return -1;
}
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;
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;
+ if (matchp->match->m)
+ free(matchp->match->m);
+ free(matchp);
+ matchp = tmp;
+ }
+
+ *matches = NULL;
+}
+
+static void set_revision(char *name, u_int8_t revision)
+{
+ /* Old kernel sources don't have ".revision" field,
+ but we stole a byte from name. */
+ name[IPT_FUNCTION_MAXNAMELEN - 2] = '\0';
+ name[IPT_FUNCTION_MAXNAMELEN - 1] = revision;
+}
+
int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
{
struct ipt_entry fw, *e = NULL;
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 = "";
memset(&fw, 0, sizeof(fw));
- opts = original_opts;
- global_option_offset = 0;
-
/* re-set optind to 0 in case do_command gets called
* a second time */
optind = 0;
/* 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;
break;
case 'N':
- if (optarg && *optarg == '-')
+ if (optarg && (*optarg == '-' || *optarg == '!'))
exit_error(PARAMETER_PROBLEM,
"chain name not allowed to start "
- "with `-'\n");
+ "with `%c'\n", *optarg);
if (find_target(optarg, TRY_LOAD))
exit_error(PARAMETER_PROBLEM,
"chain name may not clash "
optarg = argv[optind];
/* iptables -p icmp -h */
- if (!iptables_matches && protocol)
- find_match(protocol, TRY_LOAD);
+ if (!matches && protocol)
+ find_match(protocol, TRY_LOAD, &matches);
- exit_printhelp();
+ exit_printhelp(matches);
/*
* Option selection
&& (fw.ip.invflags & IPT_INV_PROTO))
exit_error(PARAMETER_PROBLEM,
"rule would never match protocol");
- fw.nfcache |= NFC_IP_PROTO;
break;
case 's':
set_option(&options, OPT_SOURCE, &fw.ip.invflags,
invert);
shostnetworkmask = argv[optind-1];
- fw.nfcache |= NFC_IP_SRC;
break;
case 'd':
set_option(&options, OPT_DESTINATION, &fw.ip.invflags,
invert);
dhostnetworkmask = argv[optind-1];
- fw.nfcache |= NFC_IP_DST;
break;
case 'j':
target->t = fw_calloc(1, size);
target->t->u.target_size = size;
strcpy(target->t->u.user.name, jumpto);
- target->init(target->t, &fw.nfcache);
+ set_revision(target->t->u.user.name,
+ target->revision);
+ if (target->init != NULL)
+ target->init(target->t, &fw.nfcache);
opts = merge_options(opts, target->extra_opts, &target->option_offset);
}
break;
parse_interface(argv[optind-1],
fw.ip.iniface,
fw.ip.iniface_mask);
- fw.nfcache |= NFC_IP_IF_IN;
break;
case 'o':
parse_interface(argv[optind-1],
fw.ip.outiface,
fw.ip.outiface_mask);
- fw.nfcache |= NFC_IP_IF_OUT;
break;
case 'f':
set_option(&options, OPT_FRAGMENT, &fw.ip.invflags,
invert);
fw.ip.flags |= IPT_F_FRAG;
- fw.nfcache |= NFC_IP_FRAG;
break;
case 'v':
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);
m->m->u.match_size = size;
strcpy(m->m->u.user.name, m->name);
- m->init(m->m, &fw.nfcache);
+ set_revision(m->m->u.user.name, m->revision);
+ if (m->init != NULL)
+ m->init(m->m, &fw.nfcache);
opts = merge_options(opts, m->extra_opts, &m->option_offset);
}
break;
"-%c requires packet and byte counter",
opt2char(OPT_COUNTERS));
- if (sscanf(pcnt, "%llu", &fw.counters.pcnt) != 1)
+ if (sscanf(pcnt, "%llu", (unsigned long long *)&fw.counters.pcnt) != 1)
exit_error(PARAMETER_PROBLEM,
"-%c packet counter not numeric",
opt2char(OPT_COUNTERS));
- if (sscanf(bcnt, "%llu", &fw.counters.bcnt) != 1)
+ if (sscanf(bcnt, "%llu", (unsigned long long *)&fw.counters.bcnt) != 1)
exit_error(PARAMETER_PROBLEM,
"-%c byte counter not numeric",
opt2char(OPT_COUNTERS));
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. */
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;
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);
+ set_revision(m->m->u.user.name,
+ m->revision);
+ if (m->init != NULL)
+ m->init(m->m, &fw.nfcache);
opts = merge_options(opts,
m->extra_opts, &m->option_offset);
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);
if (!*handle)
*handle = iptc_init(*table);
- if (!*handle) {
- /* try to insmod the module if iptc_init failed */
- iptables_insmod("ip_tables", modprobe);
+ /* try to insmod the module if iptc_init failed */
+ if (!*handle && iptables_insmod("ip_tables", modprobe) != -1)
*handle = iptc_init(*table);
- }
if (!*handle)
exit_error(VERSION_PROBLEM,
printf("Warning: using chain %s, not extension\n",
jumpto);
+ if (target->t)
+ free(target->t);
+
target = NULL;
}
target->t = fw_calloc(1, size);
target->t->u.target_size = size;
strcpy(target->t->u.user.name, jumpto);
- target->init(target->t, &fw.nfcache);
+ set_revision(target->t->u.user.name, target->revision);
+ if (target->init != NULL)
+ target->init(target->t, &fw.nfcache);
}
if (!target) {
* chain. */
find_target(jumpto, LOAD_MUST_SUCCEED);
} else {
- e = generate_entry(&fw, iptables_matches, target->t);
+ e = generate_entry(&fw, matches, target->t);
+ free(target->t);
}
}
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);
if (verbose > 1)
dump_entries(*handle);
+ clear_rule_matches(&matches);
+
+ if (e != NULL) {
+ free(e);
+ e = NULL;
+ }
+
+ free(saddrs);
+ free(daddrs);
+ free_opts(1);
+
return ret;
}