]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - tc/m_ematch.c
tc: q_red: Implement has_block for RED
[mirror_iproute2.git] / tc / m_ematch.c
index 44c621bc6fa866f6aaa29ae9d7e602312ce7bf67..8840a0dc62a16828e7592236c1a783cf760a93c8 100644 (file)
@@ -12,7 +12,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <syslog.h>
 #include <fcntl.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -33,19 +32,21 @@ static struct ematch_util *ematch_list;
 /* export to bison parser */
 int ematch_argc;
 char **ematch_argv;
-char *ematch_err = NULL;
+char *ematch_err;
 struct ematch *ematch_root;
 
 static int begin_argc;
 static char **begin_argv;
 
+static void bstr_print(FILE *fd, const struct bstr *b, int ascii);
+
 static inline void map_warning(int num, char *kind)
 {
        fprintf(stderr,
            "Error: Unable to find ematch \"%s\" in %s\n" \
            "Please assign a unique ID to the ematch kind the suggested " \
            "entry is:\n" \
-           "\t%d\t%s\n", 
+           "\t%d\t%s\n",
            kind, EMATCH_MAP, num, kind);
 }
 
@@ -66,7 +67,7 @@ static int lookup_map(__u16 num, char *dst, int len, const char *file)
                        p++;
                if (*p == '#' || *p == '\n' || *p == 0)
                        continue;
-       
+
                if (sscanf(p, "%d %s", &id, namebuf) != 2) {
                        fprintf(stderr, "ematch map %s corrupted at %s\n",
                            file, p);
@@ -104,7 +105,7 @@ static int lookup_map_id(char *kind, int *dst, const char *file)
                        p++;
                if (*p == '#' || *p == '\n' || *p == 0)
                        continue;
-       
+
                if (sscanf(p, "%d %s", &id, namebuf) != 2) {
                        fprintf(stderr, "ematch map %s corrupted at %s\n",
                            file, p);
@@ -162,14 +163,37 @@ static struct ematch_util *get_ematch_kind(char *kind)
 
 static struct ematch_util *get_ematch_kind_num(__u16 kind)
 {
-       char name[32];
+       char name[513];
 
        if (lookup_map(kind, name, sizeof(name), EMATCH_MAP) < 0)
                return NULL;
 
        return get_ematch_kind(name);
+}
+
+static int em_parse_call(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
+                        struct ematch_util *e, struct ematch *t)
+{
+       if (e->parse_eopt_argv) {
+               int argc = 0, i = 0, ret;
+               struct bstr *args;
+               char **argv;
+
+               for (args = t->args; args; args = bstr_next(args))
+                       argc++;
+               argv = calloc(argc, sizeof(char *));
+               if (!argv)
+                       return -1;
+               for (args = t->args; args; args = bstr_next(args))
+                       argv[i++] = args->data;
+
+               ret = e->parse_eopt_argv(n, hdr, argc, argv);
+
+               free(argv);
+               return ret;
+       }
 
-       return NULL;
+       return e->parse_eopt(n, hdr, t->args->next);
 }
 
 static int parse_tree(struct nlmsghdr *n, struct ematch *tree)
@@ -178,18 +202,17 @@ static int parse_tree(struct nlmsghdr *n, struct ematch *tree)
        struct ematch *t;
 
        for (t = tree; t; t = t->next) {
-               struct rtattr *tail = NLMSG_TAIL(n);
-               struct tcf_ematch_hdr hdr = {
-                       .flags = t->relation
-               };
+               struct rtattr *tail;
+               struct tcf_ematch_hdr hdr = { .flags = t->relation };
 
                if (t->inverted)
                        hdr.flags |= TCF_EM_INVERT;
-               
-               addattr_l(n, MAX_MSG, index++, NULL, 0);
+
+               tail = addattr_nest(n, MAX_MSG, index++);
 
                if (t->child) {
                        __u32 r = t->child_ref;
+
                        addraw_l(n, MAX_MSG, &hdr, sizeof(hdr));
                        addraw_l(n, MAX_MSG, &r, sizeof(r));
                } else {
@@ -200,7 +223,7 @@ static int parse_tree(struct nlmsghdr *n, struct ematch *tree)
                        if (t->args == NULL)
                                return -1;
 
-                       strncpy(buf, (char*) t->args->data, sizeof(buf)-1);
+                       strncpy(buf, (char *) t->args->data, sizeof(buf)-1);
                        e = get_ematch_kind(buf);
                        if (e == NULL) {
                                fprintf(stderr, "Unknown ematch \"%s\"\n",
@@ -216,11 +239,11 @@ static int parse_tree(struct nlmsghdr *n, struct ematch *tree)
                        }
 
                        hdr.kind = num;
-                       if (e->parse_eopt(n, &hdr, t->args->next) < 0)
+                       if (em_parse_call(n, &hdr, e, t) < 0)
                                return -1;
                }
 
-               tail->rta_len = (void*) NLMSG_TAIL(n) - (void*) tail;
+               addattr_nest_end(n, tail);
        }
 
        return 0;
@@ -256,6 +279,7 @@ static int flatten_tree(struct ematch *head, struct ematch *tree)
        return count;
 }
 
+__attribute__((format(printf, 5, 6)))
 int em_parse_error(int err, struct bstr *args, struct bstr *carg,
                   struct ematch_util *e, char *fmt, ...)
 {
@@ -278,7 +302,7 @@ int em_parse_error(int err, struct bstr *args, struct bstr *carg,
                begin_argv++;
                begin_argc--;
        }
-       
+
        fprintf(stderr, "...\n");
 
        if (args) {
@@ -345,18 +369,16 @@ int parse_ematch(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
                        .progid = TCF_EM_PROG_TC
                };
 
-               tail = NLMSG_TAIL(n);
-               addattr_l(n, MAX_MSG, tca_id, NULL, 0);
+               tail = addattr_nest(n, MAX_MSG, tca_id);
                addattr_l(n, MAX_MSG, TCA_EMATCH_TREE_HDR, &hdr, sizeof(hdr));
 
-               tail_list = NLMSG_TAIL(n);
-               addattr_l(n, MAX_MSG, TCA_EMATCH_TREE_LIST, NULL, 0);
+               tail_list = addattr_nest(n, MAX_MSG, TCA_EMATCH_TREE_LIST);
 
                if (parse_tree(n, ematch_root) < 0)
                        return -1;
 
-               tail_list->rta_len = (void*) NLMSG_TAIL(n) - (void*) tail_list;
-               tail->rta_len = (void*) NLMSG_TAIL(n) - (void*) tail;
+               addattr_nest_end(n, tail_list);
+               addattr_nest_end(n, tail);
        }
 
        *argc_p = ematch_argc;
@@ -437,7 +459,7 @@ static int print_ematch_seq(FILE *fd, struct rtattr **tb, int start,
 
                i++;
        }
-       
+
        return 0;
 }
 
@@ -451,12 +473,14 @@ static int print_ematch_list(FILE *fd, struct tcf_ematch_tree_hdr *hdr,
        if (tb == NULL)
                return -1;
 
-       if (parse_rtattr_nested(tb, hdr->nmatches, rta) < 0)
-               goto errout;
+       if (hdr->nmatches > 0) {
+               if (parse_rtattr_nested(tb, hdr->nmatches, rta) < 0)
+                       goto errout;
 
-       fprintf(fd, "\n  ");
-       if (print_ematch_seq(fd, tb, 1, 1) < 0)
-               goto errout;
+               fprintf(fd, "\n  ");
+               if (print_ematch_seq(fd, tb, 1, 1) < 0)
+                       goto errout;
+       }
 
        err = 0;
 errout:
@@ -491,3 +515,55 @@ int print_ematch(FILE *fd, const struct rtattr *rta)
 
        return print_ematch_list(fd, hdr, tb[TCA_EMATCH_TREE_LIST]);
 }
+
+struct bstr *bstr_alloc(const char *text)
+{
+       struct bstr *b = calloc(1, sizeof(*b));
+
+       if (b == NULL)
+               return NULL;
+
+       b->data = strdup(text);
+       if (b->data == NULL) {
+               free(b);
+               return NULL;
+       }
+
+       b->len = strlen(text);
+
+       return b;
+}
+
+unsigned long bstrtoul(const struct bstr *b)
+{
+       char *inv = NULL;
+       unsigned long l;
+       char buf[b->len+1];
+
+       memcpy(buf, b->data, b->len);
+       buf[b->len] = '\0';
+
+       l = strtoul(buf, &inv, 0);
+       if (l == ULONG_MAX || inv == buf)
+               return ULONG_MAX;
+
+       return l;
+}
+
+static void bstr_print(FILE *fd, const struct bstr *b, int ascii)
+{
+       int i;
+       char *s = b->data;
+
+       if (ascii)
+               for (i = 0; i < b->len; i++)
+                   fprintf(fd, "%c", isprint(s[i]) ? s[i] : '.');
+       else {
+               for (i = 0; i < b->len; i++)
+                   fprintf(fd, "%02x", s[i]);
+               fprintf(fd, "\"");
+               for (i = 0; i < b->len; i++)
+                   fprintf(fd, "%c", isprint(s[i]) ? s[i] : '.');
+               fprintf(fd, "\"");
+       }
+}