X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=tools%2Fiptables-test.c;h=881fa0b1a1aaa63cdac6e00ecdd6f636791cd76a;hb=230905c20905f2bc5ccf4b8fab75c1b5df2ac31d;hp=a7193c2e8a30519621bf589f9e2720451724c5ed;hpb=a16d6c316722e340947219de8fea6ebb3b8dce04;p=framework%2Fconnectivity%2Fconnman.git diff --git a/tools/iptables-test.c b/tools/iptables-test.c index a7193c2..881fa0b 100644 --- a/tools/iptables-test.c +++ b/tools/iptables-test.c @@ -1,7 +1,7 @@ /* * Connection Manager * - * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -46,6 +46,8 @@ static const char *hooknames[] = { #define LABEL_QUEUE "QUEUE" #define LABEL_RETURN "RETURN" +#define XT_OPTION_OFFSET_SCALE 256 + /* fn returns 0 to continue iteration */ #define _XT_ENTRY_ITERATE_CONTINUE(type, entries, size, n, fn, args...) \ ({ \ @@ -55,7 +57,7 @@ static const char *hooknames[] = { type *__entry; \ \ for (__i = 0, __n = 0; __i < (size); \ - __i += __entry->next_offset, __n++) { \ + __i += __entry->next_offset, __n++) { \ __entry = (void *)(entries) + __i; \ if (__n < n) \ continue; \ @@ -529,18 +531,17 @@ err_head: return -ENOMEM; } -static struct ipt_entry * -new_rule(struct ipt_ip *ip, char *target_name, - struct xtables_target *xt_t, - char *match_name, struct xtables_match *xt_m) +static struct ipt_entry *new_rule(struct ipt_ip *ip, + char *target_name, struct xtables_target *xt_t, + struct xtables_rule_match *xt_rm) { + struct xtables_rule_match *tmp_xt_rm; struct ipt_entry *new_entry; size_t match_size, target_size; - if (xt_m) - match_size = xt_m->m->u.match_size; - else - match_size = 0; + match_size = 0; + for (tmp_xt_rm = xt_rm; tmp_xt_rm != NULL; tmp_xt_rm = tmp_xt_rm->next) + match_size += tmp_xt_rm->match->m->u.match_size; if (xt_t) target_size = ALIGN(xt_t->t->u.target_size); @@ -557,11 +558,13 @@ new_rule(struct ipt_ip *ip, char *target_name, new_entry->target_offset = sizeof(struct ipt_entry) + match_size; new_entry->next_offset = sizeof(struct ipt_entry) + target_size + match_size; - if (xt_m) { - struct xt_entry_match *entry_match; - entry_match = (struct xt_entry_match *)new_entry->elems; - memcpy(entry_match, xt_m->m, match_size); + match_size = 0; + for (tmp_xt_rm = xt_rm; tmp_xt_rm != NULL; + tmp_xt_rm = tmp_xt_rm->next) { + memcpy(new_entry->elems + match_size, tmp_xt_rm->match->m, + tmp_xt_rm->match->m->u.match_size); + match_size += tmp_xt_rm->match->m->u.match_size; } if (xt_t) { @@ -607,8 +610,7 @@ static void update_hooks(struct connman_iptables *table, GList *chain_head, static struct ipt_entry *prepare_rule_inclusion(struct connman_iptables *table, struct ipt_ip *ip, char *chain_name, char *target_name, struct xtables_target *xt_t, - char *match_name, struct xtables_match *xt_m, - int *builtin) + int *builtin, struct xtables_rule_match *xt_rm) { GList *chain_tail, *chain_head; struct ipt_entry *new_entry; @@ -622,7 +624,7 @@ static struct ipt_entry *prepare_rule_inclusion(struct connman_iptables *table, if (chain_tail == NULL) return NULL; - new_entry = new_rule(ip, target_name, xt_t, match_name, xt_m); + new_entry = new_rule(ip, target_name, xt_t, xt_rm); if (new_entry == NULL) return NULL; @@ -644,11 +646,10 @@ static struct ipt_entry *prepare_rule_inclusion(struct connman_iptables *table, return new_entry; } -static int -connman_iptables_append_rule(struct connman_iptables *table, +static int connman_iptables_append_rule(struct connman_iptables *table, struct ipt_ip *ip, char *chain_name, char *target_name, struct xtables_target *xt_t, - char *match_name, struct xtables_match *xt_m) + struct xtables_rule_match *xt_rm) { GList *chain_tail; struct ipt_entry *new_entry; @@ -659,7 +660,7 @@ connman_iptables_append_rule(struct connman_iptables *table, return -EINVAL; new_entry = prepare_rule_inclusion(table, ip, chain_name, - target_name, xt_t, match_name, xt_m, &builtin); + target_name, xt_t, &builtin, xt_rm); if (new_entry == NULL) return -EINVAL; @@ -673,7 +674,7 @@ connman_iptables_append_rule(struct connman_iptables *table, static int connman_iptables_insert_rule(struct connman_iptables *table, struct ipt_ip *ip, char *chain_name, char *target_name, struct xtables_target *xt_t, - char *match_name, struct xtables_match *xt_m) + struct xtables_rule_match *xt_rm) { GList *chain_head; struct ipt_entry *new_entry; @@ -684,11 +685,14 @@ static int connman_iptables_insert_rule(struct connman_iptables *table, return -EINVAL; new_entry = prepare_rule_inclusion(table, ip, chain_name, - target_name, xt_t, match_name, xt_m, &builtin); + target_name, xt_t, &builtin, xt_rm); if (new_entry == NULL) return -EINVAL; - ret = connman_add_entry(table, new_entry, chain_head->next, builtin); + if (builtin == -1) + chain_head = chain_head->next; + + ret = connman_add_entry(table, new_entry, chain_head, builtin); if (ret < 0) g_free(new_entry); @@ -754,34 +758,33 @@ static gboolean is_same_match(struct xt_entry_match *xt_e_m1, return TRUE; } -static int connman_iptables_delete_rule(struct connman_iptables *table, +static GList *find_existing_rule(struct connman_iptables *table, struct ipt_ip *ip, char *chain_name, char *target_name, struct xtables_target *xt_t, - char *match_name, struct xtables_match *xt_m) + struct xtables_match *xt_m, + struct xtables_rule_match *xt_rm) { GList *chain_tail, *chain_head, *list; struct xt_entry_target *xt_e_t = NULL; struct xt_entry_match *xt_e_m = NULL; struct connman_iptables_entry *entry; struct ipt_entry *entry_test; - int builtin, removed; - - removed = 0; + int builtin; chain_head = find_chain_head(table, chain_name); if (chain_head == NULL) - return -EINVAL; + return NULL; chain_tail = find_chain_tail(table, chain_name); if (chain_tail == NULL) - return -EINVAL; + return NULL; if (!xt_t && !xt_m) - return -EINVAL; + return NULL; - entry_test = new_rule(ip, target_name, xt_t, match_name, xt_m); + entry_test = new_rule(ip, target_name, xt_t, xt_rm); if (entry_test == NULL) - return -EINVAL; + return NULL; if (xt_t != NULL) xt_e_t = ipt_get_target(entry_test); @@ -796,7 +799,7 @@ static int connman_iptables_delete_rule(struct connman_iptables *table, else list = chain_head->next; - for (entry = NULL; list != chain_tail->prev; list = list->next) { + for (; list != chain_tail->prev; list = list->next) { struct connman_iptables_entry *tmp; struct ipt_entry *tmp_e; @@ -824,14 +827,44 @@ static int connman_iptables_delete_rule(struct connman_iptables *table, continue; } - entry = tmp; break; } - if (entry == NULL) { - g_free(entry_test); + g_free(entry_test); + + if (list != chain_tail->prev) + return list; + + return NULL; +} + +static int connman_iptables_delete_rule(struct connman_iptables *table, + struct ipt_ip *ip, char *chain_name, + char *target_name, struct xtables_target *xt_t, + struct xtables_match *xt_m, + struct xtables_rule_match *xt_rm) +{ + struct connman_iptables_entry *entry; + GList *chain_tail, *list; + int builtin, removed; + + removed = 0; + + chain_tail = find_chain_tail(table, chain_name); + if (chain_tail == NULL) + return -EINVAL; + + list = find_existing_rule(table, ip, chain_name, target_name, + xt_t, xt_m, xt_rm); + if (list == NULL) + return -EINVAL; + + entry = list->data; + + if (entry == NULL) return -EINVAL; - } + + builtin = entry->builtin; /* We have deleted a rule, * all references should be bumped accordingly */ @@ -866,8 +899,58 @@ static int connman_iptables_delete_rule(struct connman_iptables *table, return 0; } -static struct ipt_replace * -connman_iptables_blob(struct connman_iptables *table) +static int connman_iptables_compare_rule(struct connman_iptables *table, + struct ipt_ip *ip, char *chain_name, + char *target_name, struct xtables_target *xt_t, + struct xtables_match *xt_m, + struct xtables_rule_match *xt_rm) +{ + struct connman_iptables_entry *entry; + GList *found; + + found = find_existing_rule(table, ip, chain_name, target_name, + xt_t, xt_m, xt_rm); + if (found == NULL) + return -EINVAL; + + entry = found->data; + if (entry == NULL) + return -EINVAL; + + return 0; +} + + +static int connman_iptables_change_policy(struct connman_iptables *table, + char *chain_name, char *policy) +{ + GList *chain_head; + struct connman_iptables_entry *entry; + struct xt_entry_target *target; + struct xt_standard_target *t; + int verdict; + + verdict = target_to_verdict(policy); + if (verdict == 0) + return -EINVAL; + + chain_head = find_chain_head(table, chain_name); + if (chain_head == NULL) + return -EINVAL; + + entry = chain_head->data; + if (entry->builtin < 0) + return -EINVAL; + + target = ipt_get_target(entry->entry); + + t = (struct xt_standard_target *)target; + t->verdict = verdict; + + return 0; +} + +static struct ipt_replace *connman_iptables_blob(struct connman_iptables *table) { struct ipt_replace *r; GList *list; @@ -1137,9 +1220,23 @@ static int add_entry(struct ipt_entry *entry, struct connman_iptables *table) static struct connman_iptables *connman_iptables_init(const char *table_name) { - struct connman_iptables *table; + struct connman_iptables *table = NULL; + char *module = NULL; socklen_t s; + if (xtables_insmod("ip_tables", NULL, TRUE) != 0) + goto err; + + module = g_strconcat("iptable_", table_name, NULL); + if (module == NULL) + goto err; + + if (xtables_insmod(module, NULL, TRUE) != 0) + goto err; + + g_free(module); + module = NULL; + table = g_try_new0(struct connman_iptables, 1); if (table == NULL) return NULL; @@ -1148,7 +1245,7 @@ static struct connman_iptables *connman_iptables_init(const char *table_name) if (table->info == NULL) goto err; - table->ipt_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); + table->ipt_sock = socket(AF_INET, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_RAW); if (table->ipt_sock < 0) goto err; @@ -1182,16 +1279,42 @@ static struct connman_iptables *connman_iptables_init(const char *table_name) table->blob_entries->size, add_entry, table); - return table; err: + g_free(module); connman_iptables_cleanup(table); return NULL; } +static struct option connman_iptables_opts[] = { + {.name = "append", .has_arg = 1, .val = 'A'}, + {.name = "compare", .has_arg = 1, .val = 'C'}, + {.name = "delete", .has_arg = 1, .val = 'D'}, + {.name = "flush-chain", .has_arg = 1, .val = 'F'}, + {.name = "insert", .has_arg = 1, .val = 'I'}, + {.name = "list", .has_arg = 2, .val = 'L'}, + {.name = "new-chain", .has_arg = 1, .val = 'N'}, + {.name = "policy", .has_arg = 1, .val = 'P'}, + {.name = "delete-chain", .has_arg = 1, .val = 'X'}, + {.name = "destination", .has_arg = 1, .val = 'd'}, + {.name = "in-interface", .has_arg = 1, .val = 'i'}, + {.name = "jump", .has_arg = 1, .val = 'j'}, + {.name = "match", .has_arg = 1, .val = 'm'}, + {.name = "out-interface", .has_arg = 1, .val = 'o'}, + {.name = "source", .has_arg = 1, .val = 's'}, + {.name = "table", .has_arg = 1, .val = 't'}, + {NULL}, +}; + +struct xtables_globals connman_iptables_globals = { + .option_offset = 0, + .opts = connman_iptables_opts, + .orig_opts = connman_iptables_opts, +}; + static struct xtables_target *prepare_target(struct connman_iptables *table, char *target_name) { @@ -1254,45 +1377,136 @@ static struct xtables_target *prepare_target(struct connman_iptables *table, xt_t->init(xt_t->t); } +#if XTABLES_VERSION_CODE > 5 + if (xt_t->x6_options != NULL) + connman_iptables_globals.opts = + xtables_options_xfrm( + connman_iptables_globals.orig_opts, + + connman_iptables_globals.opts, + xt_t->x6_options, + &xt_t->option_offset); + else +#endif + connman_iptables_globals.opts = + xtables_merge_options( +#if XTABLES_VERSION_CODE > 5 + connman_iptables_globals.orig_opts, +#endif + connman_iptables_globals.opts, + xt_t->extra_opts, + &xt_t->option_offset); + + if (connman_iptables_globals.opts == NULL) { + g_free(xt_t->t); + xt_t = NULL; + } + return xt_t; } -static struct option connman_iptables_opts[] = { - {.name = "append", .has_arg = 1, .val = 'A'}, - {.name = "delete", .has_arg = 1, .val = 'D'}, - {.name = "flush-chain", .has_arg = 1, .val = 'F'}, - {.name = "insert", .has_arg = 1, .val = 'I'}, - {.name = "list", .has_arg = 2, .val = 'L'}, - {.name = "new-chain", .has_arg = 1, .val = 'N'}, - {.name = "delete-chain", .has_arg = 1, .val = 'X'}, - {.name = "destination", .has_arg = 1, .val = 'd'}, - {.name = "in-interface", .has_arg = 1, .val = 'i'}, - {.name = "jump", .has_arg = 1, .val = 'j'}, - {.name = "match", .has_arg = 1, .val = 'm'}, - {.name = "out-interface", .has_arg = 1, .val = 'o'}, - {.name = "source", .has_arg = 1, .val = 's'}, - {.name = "table", .has_arg = 1, .val = 't'}, - {NULL}, -}; +static struct xtables_match *prepare_matches(struct connman_iptables *table, + struct xtables_rule_match **xt_rm, char *match_name) +{ + struct xtables_match *xt_m; + size_t match_size; -struct xtables_globals connman_iptables_globals = { - .option_offset = 0, - .opts = connman_iptables_opts, - .orig_opts = connman_iptables_opts, -}; + if (match_name == NULL) + return NULL; + + xt_m = xtables_find_match(match_name, XTF_LOAD_MUST_SUCCEED, xt_rm); + match_size = ALIGN(sizeof(struct ipt_entry_match)) + xt_m->size; + + xt_m->m = g_try_malloc0(match_size); + if (xt_m->m == NULL) + return NULL; + + xt_m->m->u.match_size = match_size; + strcpy(xt_m->m->u.user.name, xt_m->name); + xt_m->m->u.user.revision = xt_m->revision; + + if (xt_m->init != NULL) + xt_m->init(xt_m->m); + + if (xt_m == xt_m->next) + goto done; + +#if XTABLES_VERSION_CODE > 5 + if (xt_m->x6_options != NULL) + connman_iptables_globals.opts = + xtables_options_xfrm( + connman_iptables_globals.orig_opts, + connman_iptables_globals.opts, + xt_m->x6_options, + &xt_m->option_offset); + else +#endif + connman_iptables_globals.opts = + xtables_merge_options( +#if XTABLES_VERSION_CODE > 5 + connman_iptables_globals.orig_opts, +#endif + connman_iptables_globals.opts, + xt_m->extra_opts, + &xt_m->option_offset); + + if (connman_iptables_globals.opts == NULL) { + g_free(xt_m->m); + xt_m = NULL; + } + +done: + return xt_m; +} + +static int parse_ip_and_mask(const char *str, struct in_addr *ip, struct in_addr *mask) +{ + char **tokens; + uint32_t prefixlength; + uint32_t tmp; + int err; + + tokens = g_strsplit(str, "/", 2); + if (tokens == NULL) + return -1; + + if (!inet_pton(AF_INET, tokens[0], ip)) { + err = -1; + goto out; + } + + if (tokens[1] != NULL) { + prefixlength = strtol(tokens[1], NULL, 10); + if (prefixlength > 31) { + err = -1; + goto out; + } + + tmp = ~(0xffffffff >> prefixlength); + } else { + tmp = 0xffffffff; + } + + mask->s_addr = htonl(tmp); + ip->s_addr = ip->s_addr & mask->s_addr; + err = 0; +out: + g_strfreev(tokens); + + return err; +} int main(int argc, char *argv[]) { struct connman_iptables *table; - struct xtables_match *xt_m; + struct xtables_rule_match *xt_rm, *tmp_xt_rm; + struct xtables_match *xt_m, *xt_m_t; struct xtables_target *xt_t; struct ipt_ip ip; char *table_name, *chain, *new_chain, *match_name, *target_name; - char *delete_chain, *flush_chain; + char *delete_chain, *flush_chain, *policy; int c, in_len, out_len; - size_t size; - gboolean dump, invert, delete, insert, delete_rule; - struct in_addr src, dst; + gboolean dump, invert, delete, insert, delete_rule, compare_rule; xtables_init_all(&connman_iptables_globals, NFPROTO_IPV4); @@ -1301,26 +1515,41 @@ int main(int argc, char *argv[]) delete = FALSE; insert = FALSE; delete_rule = FALSE; - table_name = chain = new_chain = match_name = target_name = NULL; - delete_chain = flush_chain = NULL; + compare_rule = FALSE; + chain = new_chain = match_name = target_name = NULL; + delete_chain = flush_chain = policy = NULL; memset(&ip, 0, sizeof(struct ipt_ip)); table = NULL; + xt_rm = NULL; xt_m = NULL; xt_t = NULL; - while ((c = getopt_long(argc, argv, "-A:D:F:I:L::N:X:d:i:j:m:o:s:t:", + /* extension's options will generate false-positives errors */ + opterr = 0; + + while ((c = getopt_long(argc, argv, + "-A:C:D:F:I:L::N:P:X:d:i:j:m:o:s:t:", connman_iptables_globals.opts, NULL)) != -1) { switch (c) { case 'A': - /* It is either -A, -D or -I at once */ + /* It is either -A, -C, -D or -I at once */ if (chain) goto out; chain = optarg; break; + case 'C': + /* It is either -A, -C, -D or -I at once */ + if (chain) + goto out; + + chain = optarg; + compare_rule = TRUE; + break; + case 'D': - /* It is either -A, -D or -I at once */ + /* It is either -A, -C, -D or -I at once */ if (chain) goto out; @@ -1333,7 +1562,7 @@ int main(int argc, char *argv[]) break; case 'I': - /* It is either -A, -D or -I at once */ + /* It is either -A, -C, -D or -I at once */ if (chain) goto out; @@ -1349,21 +1578,28 @@ int main(int argc, char *argv[]) new_chain = optarg; break; + case 'P': + chain = optarg; + if (optind < argc) + policy = argv[optind++]; + else + goto out; + + break; + case 'X': delete = true; delete_chain = optarg; break; case 'd': - if (!inet_pton(AF_INET, optarg, &dst)) + if (!parse_ip_and_mask(optarg, &ip.dst, &ip.dmsk)) break; - ip.dst = dst; - inet_pton(AF_INET, "255.255.255.255", &ip.dmsk); - if (invert) ip.invflags |= IPT_INV_DSTIP; + break; case 'i': @@ -1382,33 +1618,17 @@ int main(int argc, char *argv[]) case 'j': target_name = optarg; + xt_t = prepare_target(table, target_name); + if (xt_t == NULL) + goto out; + break; case 'm': match_name = optarg; - - xt_m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, NULL); - size = ALIGN(sizeof(struct ipt_entry_match)) + xt_m->size; - xt_m->m = g_try_malloc0(size); + xt_m = prepare_matches(table, &xt_rm, match_name); if (xt_m == NULL) goto out; - xt_m->m->u.match_size = size; - strcpy(xt_m->m->u.user.name, xt_m->name); - xt_m->m->u.user.revision = xt_m->revision; - if (xt_m->init != NULL) - xt_m->init(xt_m->m); - if (xt_m != xt_m->next) { - connman_iptables_globals.opts = - xtables_merge_options( -#if XTABLES_VERSION_CODE > 5 - connman_iptables_globals.orig_opts, -#endif - connman_iptables_globals.opts, - xt_m->extra_opts, - &xt_m->option_offset); - if (connman_iptables_globals.opts == NULL) - goto out; - } break; @@ -1427,12 +1647,9 @@ int main(int argc, char *argv[]) break; case 's': - if (!inet_pton(AF_INET, optarg, &src)) + if (!parse_ip_and_mask(optarg, &ip.src, &ip.smsk)) break; - ip.src = src; - inet_pton(AF_INET, "255.255.255.255", &ip.smsk); - if (invert) ip.invflags |= IPT_INV_SRCIP; @@ -1440,6 +1657,11 @@ int main(int argc, char *argv[]) case 't': table_name = optarg; + + table = connman_iptables_init(table_name); + if (table == NULL) + return -1; + break; case 1: @@ -1457,26 +1679,88 @@ int main(int argc, char *argv[]) return -1; default: - if (xt_t == NULL || xt_t->parse == NULL || - !xt_t->parse(c - xt_t->option_offset, argv, invert, - &xt_t->tflags, NULL, &xt_t->t)) { - if (xt_m == NULL || xt_m->parse == NULL) - break; +#if XTABLES_VERSION_CODE > 5 + if (xt_t != NULL && (xt_t->x6_parse != NULL || + xt_t->parse != NULL) && + (c >= (int) xt_t->option_offset && + c < (int) xt_t->option_offset + + XT_OPTION_OFFSET_SCALE)) { + xtables_option_tpcall(c, argv, + invert, xt_t, NULL); - xt_m->parse(c - xt_m->option_offset, argv, - invert, &xt_m->mflags, NULL, &xt_m->m); + break; } + for (tmp_xt_rm = xt_rm; tmp_xt_rm != NULL; + tmp_xt_rm = tmp_xt_rm->next) { + xt_m_t = tmp_xt_rm->match; + + if (tmp_xt_rm->completed || + (xt_m_t->x6_parse == NULL && + xt_m_t->parse == NULL)) + continue; + + if (c < (int) xt_m_t->option_offset || + c >= (int) xt_m_t->option_offset + + XT_OPTION_OFFSET_SCALE) + continue; + + xtables_option_mpcall(c, argv, + invert, xt_m_t, NULL); + + break; + } +#else + if (xt_t == NULL || xt_t->parse == NULL || + !xt_t->parse(c - xt_t->option_offset, + argv, invert, &xt_t->tflags, NULL, &xt_t->t)) { + + for (tmp_xt_rm = xt_rm; tmp_xt_rm != NULL; + tmp_xt_rm = tmp_xt_rm->next) { + xt_m_t = tmp_xt_rm->match; + + if (tmp_xt_rm->completed || + xt_m_t->parse == NULL) + continue; + + if (xt_m->parse(c - xt_m->option_offset, + argv, invert, &xt_m->mflags, + NULL, &xt_m->m)) + break; + } + } +#endif break; } + + invert = FALSE; } - if (table_name == NULL) +#if XTABLES_VERSION_CODE > 5 + for (tmp_xt_rm = xt_rm; tmp_xt_rm != NULL; + tmp_xt_rm = tmp_xt_rm->next) + xtables_option_mfcall(tmp_xt_rm->match); + + if (xt_t != NULL) + xtables_option_tfcall(xt_t); +#else + for (tmp_xt_rm = xt_rm; tmp_xt_rm != NULL; + tmp_xt_rm = tmp_xt_rm->next) + if (tmp_xt_rm->match->final_check != NULL) + tmp_xt_rm->match->final_check( + tmp_xt_rm->match->mflags); + + if (xt_t != NULL && xt_t->final_check != NULL) + xt_t->final_check(xt_t->tflags); +#endif + + if (table == NULL) { table_name = "filter"; - table = connman_iptables_init(table_name); - if (table == NULL) - return -1; + table = connman_iptables_init(table_name); + if (table == NULL) + return -1; + } if (delete) { if (delete_chain == NULL) @@ -1515,27 +1799,34 @@ int main(int argc, char *argv[]) } if (chain) { - xt_t = prepare_target(table, target_name); - if (xt_t == NULL) - goto out; + if (policy != NULL) { + printf("Changing policy of %s to %s\n", chain, policy); + + connman_iptables_change_policy(table, chain, policy); + + goto commit; + } + + if (compare_rule == TRUE) { + int ret; + + ret = connman_iptables_compare_rule(table, &ip, + chain, target_name, xt_t, xt_m, xt_rm); + + if (ret == 0) + printf("Rule exists.\n"); + else + printf("Rule does not exist.\n"); - connman_iptables_globals.opts = - xtables_merge_options( -#if XTABLES_VERSION_CODE > 5 - connman_iptables_globals.orig_opts, -#endif - connman_iptables_globals.opts, - xt_t->extra_opts, - &xt_t->option_offset); - if (connman_iptables_globals.opts == NULL) goto out; + } if (delete_rule == TRUE) { printf("Deleting %s to %s (match %s)\n", target_name, chain, match_name); connman_iptables_delete_rule(table, &ip, chain, - target_name, xt_t, match_name, xt_m); + target_name, xt_t, xt_m, xt_rm); goto commit; } @@ -1545,13 +1836,13 @@ int main(int argc, char *argv[]) chain, match_name); connman_iptables_insert_rule(table, &ip, chain, - target_name, xt_t, match_name, xt_m); + target_name, xt_t, xt_rm); } else { printf("Appending %s to %s (match %s)\n", target_name, chain, match_name); connman_iptables_append_rule(table, &ip, chain, - target_name, xt_t, match_name, xt_m); + target_name, xt_t, xt_rm); } }