unsigned int hook,size_t size,
unsigned int offset, void *user_data);
+static unsigned int next_hook_entry_index(unsigned int *valid_hooks)
+{
+ unsigned int h;
+
+ if (*valid_hooks == 0)
+ return NF_INET_NUMHOOKS;
+
+ h = __builtin_ffs(*valid_hooks) - 1;
+ *valid_hooks ^= (1 << h);
+
+ return h;
+}
+
static int iterate_entries(struct ipt_entry *entries,
unsigned int valid_hooks,
unsigned int *hook_entry,
+ unsigned int *underflow,
size_t size, iterate_entries_cb_t cb,
void *user_data)
{
- unsigned int i, h;
+ unsigned int offset, h, hook;
int builtin, err;
struct ipt_entry *entry;
- if (valid_hooks != 0)
- h = __builtin_ffs(valid_hooks) - 1;
- else
- h = NF_INET_NUMHOOKS;
+ h = next_hook_entry_index(&valid_hooks);
+ hook = h;
- for (i = 0, entry = entries; i < size;
- i += entry->next_offset) {
+ for (offset = 0, entry = entries; offset < size;
+ offset += entry->next_offset) {
builtin = -1;
- entry = (void *)entries + i;
+ entry = (void *)entries + offset;
/*
- * Find next valid hook which offset is higher
- * or equal with the current offset.
+ * Updating builtin, hook and h is very tricky.
+ * The rules are:
+ * - builtin is only set to the current hook number
+ * if the current entry is the hook entry (aka chain
+ * head). And only for builtin chains, never for
+ * the user chains.
+ * - hook is the current hook number. If we
+ * look at user chains it needs to be NF_INET_NETNUMHOOKS.
+ * - h is the next hook entry. Thous we need to be carefully
+ * not to access the table when h is NF_INET_NETNUMHOOKS.
*/
- if (h < NF_INET_NUMHOOKS) {
- if (hook_entry[h] < i) {
- valid_hooks ^= (1 << h);
-
- if (valid_hooks != 0)
- h = __builtin_ffs(valid_hooks) - 1;
- else
- h = NF_INET_NUMHOOKS;
- }
+ if (h < NF_INET_NUMHOOKS && hook_entry[h] == offset) {
+ builtin = h;
+ hook = h;
+ }
+
+ if (h == NF_INET_NUMHOOKS)
+ hook = h;
- if (hook_entry[h] == i)
- builtin = h;
+ if (h < NF_INET_NUMHOOKS && underflow[h] <= offset) {
+ h = next_hook_entry_index(&valid_hooks);
}
- err = cb(entry, builtin, h, size, i, user_data);
+ err = cb(entry, builtin, hook, size, offset, user_data);
if (err < 0)
return err;
-
}
return 0;
struct xt_entry_target *target;
target = ipt_get_target(e->entry);
- if (!strcmp(target->u.user.name, ""))
- return true;
+ if (!g_strcmp0(target->u.user.name, IPT_STANDARD_TARGET)) {
+ struct xt_standard_target *t;
+ t = (struct xt_standard_target *)target;
+ if (t->verdict == 0)
+ return true;
+ }
return false;
}
iterate_entries(table->blob_entries->entrytable,
table->info->valid_hooks,
table->info->hook_entry,
+ table->info->underflow,
table->blob_entries->size,
print_entry, dump_entry);
}
repl->underflow[NF_IP_POST_ROUTING]);
iterate_entries(repl->entries, repl->valid_hooks,
- repl->hook_entry, repl->size, print_entry, dump_entry);
+ repl->hook_entry, repl->underflow,
+ repl->size, print_entry, dump_entry);
}
static int iptables_get_entries(struct connman_iptables *table)
iterate_entries(table->blob_entries->entrytable,
table->info->valid_hooks, table->info->hook_entry,
- table->blob_entries->size, add_entry, table);
+ table->info->underflow, table->blob_entries->size,
+ add_entry, table);
g_hash_table_insert(table_hash, g_strdup(table_name), table);
return iptables_init(table_name);
}
-static void clear_tables_flags(void)
-{
- struct xtables_match *xt_m;
- struct xtables_target *xt_t;
-
- /*
- * Clear all flags because the flags are only valid
- * for one rule.
- */
- for (xt_m = xtables_matches; xt_m != NULL; xt_m = xt_m->next)
- xt_m->mflags = 0;
-
- for (xt_t = xtables_targets; xt_t != NULL; xt_t = xt_t->next) {
- xt_t->tflags = 0;
- xt_t->used = 0;
- }
-}
-
struct parse_context {
int argc;
char **argv;
tokens = g_strsplit_set(str, " ", -1);
- for (i = 0; tokens[i]; i++);
+ i = g_strv_length(tokens);
/* Add space for the argv[0] value */
ctx->argc = i + 1;
for (i = 1; i < ctx->argc; i++)
ctx->argv[i] = tokens[i - 1];
+ g_free(tokens);
+
return 0;
}
return -ENOMEM;
/*
- * As side effect parsing a rule sets some global flags
- * which will be evaluated/verified. Let's reset them
- * to ensure we can parse more than one rule.
- */
- clear_tables_flags();
-
- /*
* Tell getopt_long not to generate error messages for unknown
* options and also reset optind back to 0.
*/
static void reset_xtables(void)
{
+ struct xtables_match *xt_m;
+ struct xtables_target *xt_t;
+
+ /*
+ * As side effect parsing a rule sets some global flags
+ * which will be evaluated/verified. Let's reset them
+ * to ensure we can parse more than one rule.
+ *
+ * Clear all flags because the flags are only valid
+ * for one rule.
+ */
+ for (xt_m = xtables_matches; xt_m != NULL; xt_m = xt_m->next)
+ xt_m->mflags = 0;
+
+ for (xt_t = xtables_targets; xt_t != NULL; xt_t = xt_t->next) {
+ xt_t->tflags = 0;
+ xt_t->used = 0;
+ }
+
/*
* We need also to free the memory implicitly allocated
* during parsing (see xtables_options_xfrm()).
static void cleanup_parse_context(struct parse_context *ctx)
{
+ struct xtables_rule_match *rm, *tmp;
+
g_strfreev(ctx->argv);
g_free(ctx->ip);
if (ctx->xt_t != NULL) {
g_free(ctx->xt_m->m);
ctx->xt_m->m = NULL;
}
+ for (tmp = NULL, rm = ctx->xt_rm; rm != NULL; rm = rm->next) {
+ if (tmp != NULL)
+ g_free(tmp);
+ tmp = rm;
+ }
+ g_free(tmp);
+
g_free(ctx);
}
iterate_entries(table->blob_entries->entrytable,
table->info->valid_hooks,
table->info->hook_entry,
+ table->info->underflow,
table->blob_entries->size,
flush_table_cb, &chains);