#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include <syslog.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
/* 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;
"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);
}
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);
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);
}
err = -ENOENT;
+ *dst = 0;
out:
fclose(fd);
return err;
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;
- return NULL;
+ ret = e->parse_eopt_argv(n, hdr, argc, argv);
+
+ free(argv);
+ return ret;
+ }
+
+ return e->parse_eopt(n, hdr, t->args->next);
}
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 {
- int num, err;
+ 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);
+ strncpy(buf, (char *) t->args->data, sizeof(buf)-1);
e = get_ematch_kind(buf);
if (e == NULL) {
fprintf(stderr, "Unknown ematch \"%s\"\n",
}
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;
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, ...)
{
begin_argv++;
begin_argc--;
}
-
+
fprintf(stderr, "...\n");
if (args) {
.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;
i++;
}
-
+
return 0;
}
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:
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;
+}
+
+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, "\"");
+ }
+}
+
+void print_ematch_tree(const struct ematch *tree)
+{
+ const struct ematch *t;
+
+ for (t = tree; t; t = t->next) {
+ if (t->inverted)
+ printf("NOT ");
+
+ if (t->child) {
+ printf("(");
+ print_ematch_tree(t->child);
+ printf(")");
+ } else {
+ struct bstr *b;
+
+ for (b = t->args; b; b = b->next)
+ printf("%s%s", b->data, b->next ? " " : "");
+ }
+
+ if (t->relation == TCF_EM_REL_AND)
+ printf(" AND ");
+ else if (t->relation == TCF_EM_REL_OR)
+ printf(" OR ");
+ }
+}