X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=tools%2Fiptables-test.c;h=881fa0b1a1aaa63cdac6e00ecdd6f636791cd76a;hb=230905c20905f2bc5ccf4b8fab75c1b5df2ac31d;hp=ac50823e8568e22e7df527ad5d0ffe56d7bb4301;hpb=dc44407d75850208300cd997aeb6f74aa4f85b6c;p=framework%2Fconnectivity%2Fconnman.git diff --git a/tools/iptables-test.c b/tools/iptables-test.c index ac50823..881fa0b 100644 --- a/tools/iptables-test.c +++ b/tools/iptables-test.c @@ -1,7 +1,7 @@ /* * Connection Manager * - * Copyright (C) 2007-2011 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 @@ -533,15 +533,15 @@ err_head: 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) + 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); @@ -558,11 +558,13 @@ static struct ipt_entry *new_rule(struct ipt_ip *ip, 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) { @@ -608,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; @@ -623,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; @@ -648,7 +649,7 @@ static struct ipt_entry *prepare_rule_inclusion(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 @@ static int 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 @@ static int 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,6 +899,57 @@ static int connman_iptables_delete_rule(struct connman_iptables *table, return 0; } +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; @@ -1207,11 +1291,13 @@ err: 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'}, @@ -1291,16 +1377,17 @@ 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( -#if XTABLES_VERSION_CODE > 5 connman_iptables_globals.orig_opts, -#endif + 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 @@ -1344,16 +1431,16 @@ static struct xtables_match *prepare_matches(struct connman_iptables *table, 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( -#if XTABLES_VERSION_CODE > 5 connman_iptables_globals.orig_opts, -#endif 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 @@ -1372,18 +1459,54 @@ 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_rule_match *xt_rm; - 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; - 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); @@ -1392,27 +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; @@ -1425,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; @@ -1441,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': @@ -1503,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; @@ -1516,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: @@ -1533,6 +1679,7 @@ int main(int argc, char *argv[]) return -1; default: +#if XTABLES_VERSION_CODE > 5 if (xt_t != NULL && (xt_t->x6_parse != NULL || xt_t->parse != NULL) && (c >= (int) xt_t->option_offset && @@ -1540,18 +1687,80 @@ int main(int argc, char *argv[]) XT_OPTION_OFFSET_SCALE)) { xtables_option_tpcall(c, argv, invert, xt_t, NULL); + + 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) @@ -1590,12 +1799,34 @@ int main(int argc, char *argv[]) } if (chain) { + 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"); + + 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; } @@ -1605,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); } }