X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=tools%2Fiptables-test.c;h=fb8cefee5f96d0dbb1ab73582495c3049eaa15d8;hb=553d7582db6124205b91c3c65f84dcaebbe30884;hp=a7193c2e8a30519621bf589f9e2720451724c5ed;hpb=a16d6c316722e340947219de8fea6ebb3b8dce04;p=framework%2Fconnectivity%2Fconnman.git diff --git a/tools/iptables-test.c b/tools/iptables-test.c index a7193c2..fb8cefe 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-2011 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,7 +685,7 @@ 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; @@ -757,7 +758,8 @@ static gboolean is_same_match(struct xt_entry_match *xt_e_m1, 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, - 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; @@ -779,7 +781,7 @@ static int connman_iptables_delete_rule(struct connman_iptables *table, if (!xt_t && !xt_m) return -EINVAL; - 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; @@ -866,8 +868,7 @@ static int connman_iptables_delete_rule(struct connman_iptables *table, return 0; } -static struct ipt_replace * -connman_iptables_blob(struct connman_iptables *table) +static struct ipt_replace *connman_iptables_blob(struct connman_iptables *table) { struct ipt_replace *r; GList *list; @@ -1137,9 +1138,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 +1163,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 +1197,40 @@ 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 = "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}, +}; + +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,43 +1293,97 @@ static struct xtables_target *prepare_target(struct connman_iptables *table, xt_t->init(xt_t->t); } + 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 + 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 (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 + 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; +} 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; int c, in_len, out_len; - size_t size; gboolean dump, invert, delete, insert, delete_rule; struct in_addr src, dst; @@ -1305,9 +1398,13 @@ int main(int argc, char *argv[]) delete_chain = flush_chain = NULL; memset(&ip, 0, sizeof(struct ipt_ip)); table = NULL; + xt_rm = NULL; xt_m = NULL; xt_t = NULL; + /* extension's options will generate false-positives errors */ + opterr = 0; + while ((c = getopt_long(argc, argv, "-A:D:F:I:L::N:X:d:i:j:m:o:s:t:", connman_iptables_globals.opts, NULL)) != -1) { switch (c) { @@ -1382,33 +1479,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; @@ -1457,20 +1538,48 @@ 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; - - xt_m->parse(c - xt_m->option_offset, argv, - invert, &xt_m->mflags, NULL, &xt_m->m); + 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); + + 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; } break; } } + 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); + if (table_name == NULL) table_name = "filter"; @@ -1515,27 +1624,12 @@ int main(int argc, char *argv[]) } if (chain) { - xt_t = prepare_target(table, target_name); - if (xt_t == NULL) - goto out; - - 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 +1639,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); } }