]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - tc/m_xt.c
tc flower: fix parsing vlan_id and vlan_prio
[mirror_iproute2.git] / tc / m_xt.c
index 48d0fb7a0bb7f449850c6cbcc70b97a5f2ba87d2..deaf96a26f7517665973ff110a2b7354127437ce 100644 (file)
--- a/tc/m_xt.c
+++ b/tc/m_xt.c
@@ -1,6 +1,6 @@
 /*
  * m_xt.c      xtables based targets
- *             utilities mostly ripped from iptables <duh, its the linux way>
+ *             utilities mostly ripped from iptables <duh, its the linux way>
  *
  *             This program is free software; you can distribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -10,7 +10,6 @@
  * Authors:  J Hadi Salim (hadi@cyberus.ca)
  */
 
-#include <syslog.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #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 +76,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 +89,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 +114,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;
-       char k[16];
+       int argc;
+       char k[FILTER_NAMESZ];
        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 +226,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 +240,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 +255,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;
@@ -243,17 +264,20 @@ static int parse_ipt(struct action_util *a,int *argc_p,
                }
        }
 
-       tail = NLMSG_TAIL(n);
-       addattr_l(n, MAX_MSG, tca_id, NULL, 0);
+       tail = addattr_nest(n, MAX_MSG, tca_id);
        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);
@@ -265,11 +289,10 @@ static int parse_ipt(struct action_util *a,int *argc_p,
        addattr_l(n, MAX_MSG, TCA_IPT_INDEX, &index, 4);
        if (m)
                addattr_l(n, MAX_MSG, TCA_IPT_TARG, m->t, m->t->u.target_size);
-       tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
+       addattr_nest_end(n, tail);
 
-       argc -= optind;
        argv += optind;
-       *argc_p = rargc - iargc;
+       *argc_p -= argc;
        *argv_p = argv;
 
        optind = 0;
@@ -289,14 +312,15 @@ 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;
+       __u32 hook;
 
        if (arg == NULL)
-               return -1;
+               return 0;
 
        /* copy tcipt_globals because .opts will be modified by iptables */
        struct xtables_globals tmp_tcipt_globals = tcipt_globals;
@@ -307,84 +331,75 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg)
        parse_rtattr_nested(tb, TCA_IPT_MAX, arg);
 
        if (tb[TCA_IPT_TABLE] == NULL) {
-               fprintf(f, "[NULL ipt table name ] assuming mangle ");
+               fprintf(stderr, "Missing ipt table name, assuming mangle\n");
        } else {
                fprintf(f, "tablename: %s ",
                        rta_getattr_str(tb[TCA_IPT_TABLE]));
        }
 
        if (tb[TCA_IPT_HOOK] == NULL) {
-               fprintf(f, "[NULL ipt hook name ]\n ");
+               fprintf(stderr, "Missing ipt hook name\n ");
                return -1;
-       } else {
-               __u32 hook;
-               hook = rta_getattr_u32(tb[TCA_IPT_HOOK]);
-               fprintf(f, " hook: %s \n", ipthooks[hook]);
        }
 
        if (tb[TCA_IPT_TARG] == NULL) {
-               fprintf(f, "\t[NULL ipt target parameters ] \n");
+               fprintf(stderr, "Missing 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);
+       hook = rta_getattr_u32(tb[TCA_IPT_HOOK]);
+       fprintf(f, " hook: %s\n", ipthooks[hook]);
+
+       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);
+               }
+       }
+       print_nl();
+
        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,
 };