X-Git-Url: http://git.onelab.eu/?p=iproute2.git;a=blobdiff_plain;f=tc%2Fm_ematch.c;fp=tc%2Fm_ematch.c;h=0000000000000000000000000000000000000000;hp=44c621bc6fa866f6aaa29ae9d7e602312ce7bf67;hb=3331a68859fd71047bb1f309048960b48eab2d83;hpb=2bd4a72f2100be7ad7d9518cb1d49bb2a5b71994 diff --git a/tc/m_ematch.c b/tc/m_ematch.c deleted file mode 100644 index 44c621b..0000000 --- a/tc/m_ematch.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * m_ematch.c Extended Matches - * - * This program is free software; you can distribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Authors: Thomas Graf - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "utils.h" -#include "tc_util.h" -#include "m_ematch.h" - -#define EMATCH_MAP "/etc/iproute2/ematch_map" - -static struct ematch_util *ematch_list; - -/* export to bison parser */ -int ematch_argc; -char **ematch_argv; -char *ematch_err = NULL; -struct ematch *ematch_root; - -static int begin_argc; -static char **begin_argv; - -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", - kind, EMATCH_MAP, num, kind); -} - -static int lookup_map(__u16 num, char *dst, int len, const char *file) -{ - int err = -EINVAL; - char buf[512]; - FILE *fd = fopen(file, "r"); - - if (fd == NULL) - return -errno; - - while (fgets(buf, sizeof(buf), fd)) { - char namebuf[512], *p = buf; - int id; - - while (*p == ' ' || *p == '\t') - 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); - goto out; - } - - if (id == num) { - if (dst) - strncpy(dst, namebuf, len - 1); - err = 0; - goto out; - } - } - - err = -ENOENT; -out: - fclose(fd); - return err; -} - -static int lookup_map_id(char *kind, int *dst, const char *file) -{ - int err = -EINVAL; - char buf[512]; - FILE *fd = fopen(file, "r"); - - if (fd == NULL) - return -errno; - - while (fgets(buf, sizeof(buf), fd)) { - char namebuf[512], *p = buf; - int id; - - while (*p == ' ' || *p == '\t') - 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); - goto out; - } - - if (!strcasecmp(namebuf, kind)) { - if (dst) - *dst = id; - err = 0; - goto out; - } - } - - err = -ENOENT; - *dst = 0; -out: - fclose(fd); - return err; -} - -static struct ematch_util *get_ematch_kind(char *kind) -{ - static void *body; - void *dlh; - char buf[256]; - struct ematch_util *e; - - for (e = ematch_list; e; e = e->next) { - if (strcmp(e->kind, kind) == 0) - return e; - } - - snprintf(buf, sizeof(buf), "em_%s.so", kind); - dlh = dlopen(buf, RTLD_LAZY); - if (dlh == NULL) { - dlh = body; - if (dlh == NULL) { - dlh = body = dlopen(NULL, RTLD_LAZY); - if (dlh == NULL) - return NULL; - } - } - - snprintf(buf, sizeof(buf), "%s_ematch_util", kind); - e = dlsym(dlh, buf); - if (e == NULL) - return NULL; - - e->next = ematch_list; - ematch_list = e; - - return e; -} - -static struct ematch_util *get_ematch_kind_num(__u16 kind) -{ - char name[32]; - - if (lookup_map(kind, name, sizeof(name), EMATCH_MAP) < 0) - return NULL; - - return get_ematch_kind(name); - - return NULL; -} - -static int parse_tree(struct nlmsghdr *n, struct ematch *tree) -{ - int index = 1; - struct ematch *t; - - for (t = tree; t; t = t->next) { - struct rtattr *tail = NLMSG_TAIL(n); - struct tcf_ematch_hdr hdr = { - .flags = t->relation - }; - - if (t->inverted) - hdr.flags |= TCF_EM_INVERT; - - addattr_l(n, MAX_MSG, index++, NULL, 0); - - 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 { - int num = 0, err; - char buf[64]; - struct ematch_util *e; - - if (t->args == NULL) - return -1; - - strncpy(buf, (char*) t->args->data, sizeof(buf)-1); - e = get_ematch_kind(buf); - if (e == NULL) { - fprintf(stderr, "Unknown ematch \"%s\"\n", - buf); - return -1; - } - - err = lookup_map_id(buf, &num, EMATCH_MAP); - if (err < 0) { - if (err == -ENOENT) - map_warning(e->kind_num, buf); - return err; - } - - hdr.kind = num; - if (e->parse_eopt(n, &hdr, t->args->next) < 0) - return -1; - } - - tail->rta_len = (void*) NLMSG_TAIL(n) - (void*) tail; - } - - return 0; -} - -static int flatten_tree(struct ematch *head, struct ematch *tree) -{ - int i, count = 0; - struct ematch *t; - - for (;;) { - count++; - - if (tree->child) { - for (t = head; t->next; t = t->next); - t->next = tree->child; - count += flatten_tree(head, tree->child); - } - - if (tree->relation == 0) - break; - - tree = tree->next; - } - - for (i = 0, t = head; t; t = t->next, i++) - t->index = i; - - for (t = head; t; t = t->next) - if (t->child) - t->child_ref = t->child->index; - - return count; -} - -int em_parse_error(int err, struct bstr *args, struct bstr *carg, - struct ematch_util *e, char *fmt, ...) -{ - va_list a; - - va_start(a, fmt); - vfprintf(stderr, fmt, a); - va_end(a); - - if (ematch_err) - fprintf(stderr, ": %s\n... ", ematch_err); - else - fprintf(stderr, "\n... "); - - while (ematch_argc < begin_argc) { - if (ematch_argc == (begin_argc - 1)) - fprintf(stderr, ">>%s<< ", *begin_argv); - else - fprintf(stderr, "%s ", *begin_argv); - begin_argv++; - begin_argc--; - } - - fprintf(stderr, "...\n"); - - if (args) { - fprintf(stderr, "... %s(", e->kind); - while (args) { - fprintf(stderr, "%s", args == carg ? ">>" : ""); - bstr_print(stderr, args, 1); - fprintf(stderr, "%s%s", args == carg ? "<<" : "", - args->next ? " " : ""); - args = args->next; - } - fprintf(stderr, ")...\n"); - - } - - if (e == NULL) { - fprintf(stderr, - "Usage: EXPR\n" \ - "where: EXPR := TERM [ { and | or } EXPR ]\n" \ - " TERM := [ not ] { MATCH | '(' EXPR ')' }\n" \ - " MATCH := module '(' ARGS ')'\n" \ - " ARGS := ARG1 ARG2 ...\n" \ - "\n" \ - "Example: a(x y) and not (b(x) or c(x y z))\n"); - } else - e->print_usage(stderr); - - return -err; -} - -static inline void free_ematch_err(void) -{ - if (ematch_err) { - free(ematch_err); - ematch_err = NULL; - } -} - -extern int ematch_parse(void); - -int parse_ematch(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) -{ - begin_argc = ematch_argc = *argc_p; - begin_argv = ematch_argv = *argv_p; - - if (ematch_parse()) { - int err = em_parse_error(EINVAL, NULL, NULL, NULL, - "Parse error"); - free_ematch_err(); - return err; - } - - free_ematch_err(); - - /* undo look ahead by parser */ - ematch_argc++; - ematch_argv--; - - if (ematch_root) { - struct rtattr *tail, *tail_list; - - struct tcf_ematch_tree_hdr hdr = { - .nmatches = flatten_tree(ematch_root, ematch_root), - .progid = TCF_EM_PROG_TC - }; - - tail = NLMSG_TAIL(n); - addattr_l(n, MAX_MSG, tca_id, NULL, 0); - 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); - - 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; - } - - *argc_p = ematch_argc; - *argv_p = ematch_argv; - - return 0; -} - -static int print_ematch_seq(FILE *fd, struct rtattr **tb, int start, - int prefix) -{ - int n, i = start; - struct tcf_ematch_hdr *hdr; - int dlen; - void *data; - - for (;;) { - if (tb[i] == NULL) - return -1; - - dlen = RTA_PAYLOAD(tb[i]) - sizeof(*hdr); - data = (void *) RTA_DATA(tb[i]) + sizeof(*hdr); - - if (dlen < 0) - return -1; - - hdr = RTA_DATA(tb[i]); - - if (hdr->flags & TCF_EM_INVERT) - fprintf(fd, "NOT "); - - if (hdr->kind == 0) { - __u32 ref; - - if (dlen < sizeof(__u32)) - return -1; - - ref = *(__u32 *) data; - fprintf(fd, "(\n"); - for (n = 0; n <= prefix; n++) - fprintf(fd, " "); - if (print_ematch_seq(fd, tb, ref + 1, prefix + 1) < 0) - return -1; - for (n = 0; n < prefix; n++) - fprintf(fd, " "); - fprintf(fd, ") "); - - } else { - struct ematch_util *e; - - e = get_ematch_kind_num(hdr->kind); - if (e == NULL) - fprintf(fd, "[unknown ematch %d]\n", - hdr->kind); - else { - fprintf(fd, "%s(", e->kind); - if (e->print_eopt(fd, hdr, data, dlen) < 0) - return -1; - fprintf(fd, ")\n"); - } - if (hdr->flags & TCF_EM_REL_MASK) - for (n = 0; n < prefix; n++) - fprintf(fd, " "); - } - - switch (hdr->flags & TCF_EM_REL_MASK) { - case TCF_EM_REL_AND: - fprintf(fd, "AND "); - break; - - case TCF_EM_REL_OR: - fprintf(fd, "OR "); - break; - - default: - return 0; - } - - i++; - } - - return 0; -} - -static int print_ematch_list(FILE *fd, struct tcf_ematch_tree_hdr *hdr, - struct rtattr *rta) -{ - int err = -1; - struct rtattr **tb; - - tb = malloc((hdr->nmatches + 1) * sizeof(struct rtattr *)); - if (tb == NULL) - return -1; - - 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; - - err = 0; -errout: - free(tb); - return err; -} - -int print_ematch(FILE *fd, const struct rtattr *rta) -{ - struct rtattr *tb[TCA_EMATCH_TREE_MAX+1]; - struct tcf_ematch_tree_hdr *hdr; - - if (parse_rtattr_nested(tb, TCA_EMATCH_TREE_MAX, rta) < 0) - return -1; - - if (tb[TCA_EMATCH_TREE_HDR] == NULL) { - fprintf(stderr, "Missing ematch tree header\n"); - return -1; - } - - if (tb[TCA_EMATCH_TREE_LIST] == NULL) { - fprintf(stderr, "Missing ematch tree list\n"); - return -1; - } - - if (RTA_PAYLOAD(tb[TCA_EMATCH_TREE_HDR]) < sizeof(*hdr)) { - fprintf(stderr, "Ematch tree header size mismatch\n"); - return -1; - } - - hdr = RTA_DATA(tb[TCA_EMATCH_TREE_HDR]); - - return print_ematch_list(fd, hdr, tb[TCA_EMATCH_TREE_LIST]); -}