diff options
Diffstat (limited to 'tc/m_xt.c')
-rw-r--r-- | tc/m_xt.c | 254 |
1 files changed, 136 insertions, 118 deletions
@@ -39,19 +39,21 @@ #endif #ifndef __ALIGN_KERNEL -#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1) -#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define __ALIGN_KERNEL(x, a) \ + __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1) +#define __ALIGN_KERNEL_MASK(x, mask) \ + (((x) + (mask)) & ~(mask)) #endif #ifndef ALIGN -#define ALIGN(x,a) __ALIGN_KERNEL((x), (a)) +#define ALIGN(x, a) __ALIGN_KERNEL((x), (a)) #endif static const char *tname = "mangle"; char *lib_dir; -static const char *ipthooks[] = { +static const char * const ipthooks[] = { "NF_IP_PRE_ROUTING", "NF_IP_LOCAL_IN", "NF_IP_FORWARD", @@ -75,6 +77,9 @@ static struct xtables_globals tcipt_globals = { .orig_opts = original_opts, .opts = original_opts, .exit_err = NULL, +#if XTABLES_VERSION_CODE >= 11 + .compat_rev = xtables_compatible_revision, +#endif }; /* @@ -85,12 +90,13 @@ build_st(struct xtables_target *target, struct xt_entry_target *t) { size_t size = - XT_ALIGN(sizeof (struct xt_entry_target)) + target->size; + XT_ALIGN(sizeof(struct xt_entry_target)) + target->size; - if (NULL == t) { + if (t == NULL) { target->t = xtables_calloc(1, size); target->t->u.target_size = size; - strcpy(target->t->u.user.name, target->name); + strncpy(target->t->u.user.name, target->name, + sizeof(target->t->u.user.name) - 1); target->t->u.user.revision = target->revision; if (target->init != NULL) @@ -109,95 +115,110 @@ static void set_lib_dir(void) if (!lib_dir) { lib_dir = getenv("IPTABLES_LIB_DIR"); if (lib_dir) - fprintf(stderr, "using deprecated IPTABLES_LIB_DIR \n"); + fprintf(stderr, "using deprecated IPTABLES_LIB_DIR\n"); } if (lib_dir == NULL) lib_dir = XT_LIB_DIR; } -static int parse_ipt(struct action_util *a,int *argc_p, +static int get_xtables_target_opts(struct xtables_globals *globals, + struct xtables_target *m) +{ + struct option *opts; + +#if XTABLES_VERSION_CODE >= 6 + opts = xtables_options_xfrm(globals->orig_opts, + globals->opts, + m->x6_options, + &m->option_offset); +#else + opts = xtables_merge_options(globals->opts, + m->extra_opts, + &m->option_offset); +#endif + if (!opts) + return -1; + globals->opts = opts; + return 0; +} + +static int parse_ipt(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { struct xtables_target *m = NULL; - struct ipt_entry fw; +#if XTABLES_VERSION_CODE >= 6 + struct ipt_entry fw = {}; +#endif struct rtattr *tail; int c; - int rargc = *argc_p; char **argv = *argv_p; - int argc = 0, iargc = 0; + int argc; char k[16]; int size = 0; int iok = 0, ok = 0; __u32 hook = 0, index = 0; - struct option *opts = NULL; - xtables_init_all(&tcipt_globals, NFPROTO_IPV4); + /* copy tcipt_globals because .opts will be modified by iptables */ + struct xtables_globals tmp_tcipt_globals = tcipt_globals; + + xtables_init_all(&tmp_tcipt_globals, NFPROTO_IPV4); set_lib_dir(); - { - int i; - for (i = 0; i < rargc; i++) { - if (NULL == argv[i] || 0 == strcmp(argv[i], "action")) { - break; - } - } - iargc = argc = i; + /* parse only up until the next action */ + for (argc = 0; argc < *argc_p; argc++) { + if (!argv[argc] || !strcmp(argv[argc], "action")) + break; } if (argc <= 2) { - fprintf(stderr,"bad arguments to ipt %d vs %d \n", argc, rargc); + fprintf(stderr, + "too few arguments for xt, need at least '-j <target>'\n"); return -1; } while (1) { - c = getopt_long(argc, argv, "j:", tcipt_globals.opts, NULL); + c = getopt_long(argc, argv, "j:", tmp_tcipt_globals.opts, NULL); if (c == -1) break; switch (c) { case 'j': m = xtables_find_target(optarg, XTF_TRY_LOAD); - if (NULL != m) { - - if (0 > build_st(m, NULL)) { - printf(" %s error \n", m->name); - return -1; - } -#if (XTABLES_VERSION_CODE >= 6) - opts = xtables_options_xfrm(tcipt_globals.orig_opts, - tcipt_globals.opts, - m->x6_options, - &m->option_offset); -#else - opts = xtables_merge_options(tcipt_globals.opts, - m->extra_opts, - &m->option_offset); -#endif - if (opts == NULL) { - fprintf(stderr, " failed to find additional options for target %s\n\n", optarg); + if (!m) { + fprintf(stderr, + " failed to find target %s\n\n", + optarg); return -1; - } else - tcipt_globals.opts = opts; - } else { - fprintf(stderr," failed to find target %s\n\n", optarg); + } + + if (build_st(m, NULL) < 0) { + printf(" %s error\n", m->name); + return -1; + } + + if (get_xtables_target_opts(&tmp_tcipt_globals, + m) < 0) { + fprintf(stderr, + " failed to find additional options for target %s\n\n", + optarg); return -1; } ok++; break; default: - memset(&fw, 0, sizeof (fw)); -#if (XTABLES_VERSION_CODE >= 6) - if (m != NULL && m->x6_parse != NULL ) { - xtables_option_tpcall(c, argv, 0 , m, NULL); +#if XTABLES_VERSION_CODE >= 6 + if (m != NULL && m->x6_parse != NULL) { + xtables_option_tpcall(c, argv, 0, m, &fw); #else - if (m != NULL && m->parse != NULL ) { - m->parse(c - m->option_offset, argv, 0, &m->tflags, - NULL, &m->t); + if (m != NULL && m->parse != NULL) { + m->parse(c - m->option_offset, argv, 0, + &m->tflags, NULL, &m->t); #endif } else { - fprintf(stderr,"failed to find target %s\n\n", optarg); + fprintf(stderr, + "failed to find target %s\n\n", optarg); return -1; } @@ -206,7 +227,7 @@ static int parse_ipt(struct action_util *a,int *argc_p, } } - if (iargc > optind) { + if (argc > optind) { if (matches(argv[optind], "index") == 0) { if (get_u32(&index, argv[optind + 1], 10)) { fprintf(stderr, "Illegal \"index\"\n"); @@ -220,12 +241,12 @@ static int parse_ipt(struct action_util *a,int *argc_p, } if (!ok && !iok) { - fprintf(stderr," ipt Parser BAD!! (%s)\n", *argv); + fprintf(stderr, " ipt Parser BAD!! (%s)\n", *argv); return -1; } /* check that we passed the correct parameters to the target */ -#if (XTABLES_VERSION_CODE >= 6) +#if XTABLES_VERSION_CODE >= 6 if (m) xtables_option_tfcall(m); #else @@ -235,6 +256,7 @@ static int parse_ipt(struct action_util *a,int *argc_p, { struct tcmsg *t = NLMSG_DATA(n); + if (t->tcm_parent != TC_H_ROOT && t->tcm_parent == TC_H_MAJ(TC_H_INGRESS)) { hook = NF_IP_PRE_ROUTING; @@ -248,12 +270,16 @@ static int parse_ipt(struct action_util *a,int *argc_p, fprintf(stdout, "tablename: %s hook: %s\n ", tname, ipthooks[hook]); fprintf(stdout, "\ttarget: "); - if (m) - m->print(NULL, m->t, 0); + if (m) { + if (m->print) + m->print(NULL, m->t, 0); + else + printf("%s ", m->name); + } fprintf(stdout, " index %d\n", index); - if (strlen(tname) > 16) { - size = 16; + if (strlen(tname) >= 16) { + size = 15; k[15] = 0; } else { size = 1 + strlen(tname); @@ -267,9 +293,8 @@ static int parse_ipt(struct action_util *a,int *argc_p, addattr_l(n, MAX_MSG, TCA_IPT_TARG, m->t, m->t->u.target_size); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; - argc -= optind; argv += optind; - *argc_p = rargc - iargc; + *argc_p -= argc; *argv_p = argv; optind = 0; @@ -289,11 +314,11 @@ static int parse_ipt(struct action_util *a,int *argc_p, } static int -print_ipt(struct action_util *au,FILE * f, struct rtattr *arg) +print_ipt(struct action_util *au, FILE *f, struct rtattr *arg) { + struct xtables_target *m; struct rtattr *tb[TCA_IPT_MAX + 1]; struct xt_entry_target *t = NULL; - struct option *opts = NULL; if (arg == NULL) return -1; @@ -318,73 +343,66 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg) return -1; } else { __u32 hook; + hook = rta_getattr_u32(tb[TCA_IPT_HOOK]); - fprintf(f, " hook: %s \n", ipthooks[hook]); + fprintf(f, " hook: %s\n", ipthooks[hook]); } if (tb[TCA_IPT_TARG] == NULL) { - fprintf(f, "\t[NULL ipt target parameters ] \n"); + fprintf(f, "\t[NULL ipt target parameters ]\n"); return -1; - } else { - struct xtables_target *m = NULL; - t = RTA_DATA(tb[TCA_IPT_TARG]); - m = xtables_find_target(t->u.user.name, XTF_TRY_LOAD); - if (NULL != m) { - if (0 > build_st(m, t)) { - fprintf(stderr, " %s error \n", m->name); - return -1; - } + } -#if (XTABLES_VERSION_CODE >= 6) - opts = xtables_options_xfrm(tmp_tcipt_globals.orig_opts, - tmp_tcipt_globals.opts, - m->x6_options, - &m->option_offset); -#else - opts = xtables_merge_options(tmp_tcipt_globals.opts, - m->extra_opts, - &m->option_offset); -#endif - if (opts == NULL) { - fprintf(stderr, " failed to find additional options for target %s\n\n", optarg); + t = RTA_DATA(tb[TCA_IPT_TARG]); + m = xtables_find_target(t->u.user.name, XTF_TRY_LOAD); + if (!m) { + fprintf(stderr, " failed to find target %s\n\n", + t->u.user.name); return -1; - } else - tmp_tcipt_globals.opts = opts; - } else { - fprintf(stderr, " failed to find target %s\n\n", - t->u.user.name); - return -1; - } - fprintf(f, "\ttarget "); - m->print(NULL, m->t, 0); - if (tb[TCA_IPT_INDEX] == NULL) { - fprintf(f, " [NULL ipt target index ]\n"); - } else { - __u32 index; - index = rta_getattr_u32(tb[TCA_IPT_INDEX]); - fprintf(f, " \n\tindex %d", index); - } + } + if (build_st(m, t) < 0) { + fprintf(stderr, " %s error\n", m->name); + return -1; + } - if (tb[TCA_IPT_CNT]) { - struct tc_cnt *c = RTA_DATA(tb[TCA_IPT_CNT]);; - fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt); - } - if (show_stats) { - if (tb[TCA_IPT_TM]) { - struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]); - print_tm(f,tm); - } - } - fprintf(f, " \n"); + if (get_xtables_target_opts(&tmp_tcipt_globals, m) < 0) { + fprintf(stderr, + " failed to find additional options for target %s\n\n", + t->u.user.name); + return -1; + } + fprintf(f, "\ttarget "); + m->print(NULL, m->t, 0); + if (tb[TCA_IPT_INDEX] == NULL) { + fprintf(f, " [NULL ipt target index ]\n"); + } else { + __u32 index; + index = rta_getattr_u32(tb[TCA_IPT_INDEX]); + fprintf(f, "\n\tindex %u", index); } + + if (tb[TCA_IPT_CNT]) { + struct tc_cnt *c = RTA_DATA(tb[TCA_IPT_CNT]); + + fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt); + } + if (show_stats) { + if (tb[TCA_IPT_TM]) { + struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]); + + print_tm(f, tm); + } + } + fprintf(f, "\n"); + xtables_free_opts(1); return 0; } struct action_util xt_action_util = { - .id = "xt", - .parse_aopt = parse_ipt, - .print_aopt = print_ipt, + .id = "xt", + .parse_aopt = parse_ipt, + .print_aopt = print_ipt, }; |