m_ematch.c revision 7a473c77e613e4174dff0585d5c0f4f1cd9a21ee
17a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger/* 27a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger * m_ematch.c Extended Matches 37a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger * 47a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger * This program is free software; you can distribute it and/or 57a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger * modify it under the terms of the GNU General Public License 67a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger * as published by the Free Software Foundation; either version 77a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger * 2 of the License, or (at your option) any later version. 87a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger * 97a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger * Authors: Thomas Graf <tgraf@suug.ch> 107a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger */ 117a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 127a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include <stdio.h> 137a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include <stdlib.h> 147a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include <unistd.h> 157a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include <syslog.h> 167a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include <fcntl.h> 177a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include <sys/socket.h> 187a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include <netinet/in.h> 197a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include <arpa/inet.h> 207a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include <string.h> 217a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include <dlfcn.h> 227a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include <stdarg.h> 237a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include <errno.h> 247a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 257a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include "utils.h" 267a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include "tc_util.h" 277a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#include "m_ematch.h" 287a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 297a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger#define EMATCH_MAP "/etc/iproute2/ematch_map" 307a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 317a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic struct ematch_util *ematch_list; 327a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 337a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger/* export to bison parser */ 347a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerint ematch_argc; 357a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerchar **ematch_argv; 367a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerchar *ematch_err = NULL; 377a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstruct ematch *ematch_root; 387a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 397a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic int begin_argc; 407a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic char **begin_argv; 417a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 427a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic inline void map_warning(int num, char *kind) 437a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 447a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, 457a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger "Error: Unable to find ematch \"%s\" in %s\n" \ 467a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger "Please assign a unique ID to the ematch kind the suggested " \ 477a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger "entry is:\n" \ 487a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger "\t%d\t%s\n", 497a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger kind, EMATCH_MAP, num, kind); 507a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 517a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 527a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic int lookup_map(__u16 num, char *dst, int len, const char *file) 537a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 547a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int err = -EINVAL; 557a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger char buf[512]; 567a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger FILE *fd = fopen(file, "r"); 577a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 587a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (fd == NULL) 597a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -errno; 607a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 617a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger while (fgets(buf, sizeof(buf), fd)) { 627a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger char namebuf[512], *p = buf; 637a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int id; 647a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 657a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger while (*p == ' ' || *p == '\t') 667a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger p++; 677a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (*p == '#' || *p == '\n' || *p == 0) 687a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger continue; 697a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 707a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (sscanf(p, "%d %s", &id, namebuf) != 2) { 717a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "ematch map %s corrupted at %s\n", 727a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger file, p); 737a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger goto out; 747a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 757a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 767a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (id == num) { 777a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (dst) 787a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger strncpy(dst, namebuf, len - 1); 797a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger err = 0; 807a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger goto out; 817a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 827a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 837a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 847a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger err = -ENOENT; 857a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerout: 867a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fclose(fd); 877a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return err; 887a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 897a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 907a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic int lookup_map_id(char *kind, int *dst, const char *file) 917a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 927a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int err = -EINVAL; 937a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger char buf[512]; 947a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger FILE *fd = fopen(file, "r"); 957a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 967a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (fd == NULL) 977a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -errno; 987a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 997a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger while (fgets(buf, sizeof(buf), fd)) { 1007a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger char namebuf[512], *p = buf; 1017a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int id; 1027a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1037a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger while (*p == ' ' || *p == '\t') 1047a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger p++; 1057a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (*p == '#' || *p == '\n' || *p == 0) 1067a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger continue; 1077a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1087a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (sscanf(p, "%d %s", &id, namebuf) != 2) { 1097a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "ematch map %s corrupted at %s\n", 1107a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger file, p); 1117a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger goto out; 1127a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 1137a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1147a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (!strcasecmp(namebuf, kind)) { 1157a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (dst) 1167a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger *dst = id; 1177a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger err = 0; 1187a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger goto out; 1197a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 1207a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 1217a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1227a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger err = -ENOENT; 1237a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerout: 1247a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fclose(fd); 1257a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return err; 1267a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 1277a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1287a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic struct ematch_util *get_ematch_kind(char *kind) 1297a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 1307a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger static void *body; 1317a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger void *dlh; 1327a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger char buf[256]; 1337a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct ematch_util *e; 1347a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1357a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (e = ematch_list; e; e = e->next) { 1367a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (strcmp(e->kind, kind) == 0) 1377a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return e; 1387a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 1397a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1407a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger snprintf(buf, sizeof(buf), "em_%s.so", kind); 1417a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger dlh = dlopen(buf, RTLD_LAZY); 1427a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (dlh == NULL) { 1437a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger dlh = body; 1447a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (dlh == NULL) { 1457a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger dlh = body = dlopen(NULL, RTLD_LAZY); 1467a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (dlh == NULL) 1477a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return NULL; 1487a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 1497a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 1507a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1517a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger snprintf(buf, sizeof(buf), "%s_ematch_util", kind); 1527a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger e = dlsym(dlh, buf); 1537a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (e == NULL) 1547a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return NULL; 1557a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1567a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger e->next = ematch_list; 1577a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger ematch_list = e; 1587a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1597a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return e; 1607a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 1617a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1627a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic struct ematch_util *get_ematch_kind_num(__u16 kind) 1637a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 1647a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger char name[32]; 1657a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1667a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (lookup_map(kind, name, sizeof(name), EMATCH_MAP) < 0) 1677a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return NULL; 1687a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1697a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return get_ematch_kind(name); 1707a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1717a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return NULL; 1727a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 1737a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1747a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic int parse_tree(struct nlmsghdr *n, struct ematch *tree) 1757a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 1767a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int index = 1; 1777a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct ematch *t; 1787a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1797a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (t = tree; t; t = t->next) { 1807a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct rtattr *tail = NLMSG_TAIL(n); 1817a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct tcf_ematch_hdr hdr = { 1827a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger .flags = t->relation 1837a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger }; 1847a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1857a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (t->inverted) 1867a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger hdr.flags |= TCF_EM_INVERT; 1877a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1887a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger addattr_l(n, MAX_MSG, index++, NULL, 0); 1897a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1907a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (t->child) { 1917a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger __u32 r = t->child_ref; 1927a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger addraw_l(n, MAX_MSG, &hdr, sizeof(hdr)); 1937a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger addraw_l(n, MAX_MSG, &r, sizeof(r)); 1947a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } else { 1957a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int num, err; 1967a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger char buf[64]; 1977a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct ematch_util *e; 1987a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1997a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (t->args == NULL) 2007a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 2017a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2027a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger strncpy(buf, (char*) t->args->data, sizeof(buf)-1); 2037a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger e = get_ematch_kind(buf); 2047a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (e == NULL) { 2057a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "Unknown ematch \"%s\"\n", 2067a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger buf); 2077a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 2087a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2097a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2107a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger err = lookup_map_id(buf, &num, EMATCH_MAP); 2117a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (err < 0) { 2127a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (err == -ENOENT) 2137a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger map_warning(e->kind_num, buf); 2147a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return err; 2157a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2167a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2177a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger hdr.kind = num; 2187a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (e->parse_eopt(n, &hdr, t->args->next) < 0) 2197a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 2207a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2217a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2227a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger tail->rta_len = (void*) NLMSG_TAIL(n) - (void*) tail; 2237a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2247a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2257a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return 0; 2267a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 2277a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2287a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic int flatten_tree(struct ematch *head, struct ematch *tree) 2297a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 2307a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int i, count = 0; 2317a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct ematch *t; 2327a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2337a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (;;) { 2347a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger count++; 2357a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2367a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (tree->child) { 2377a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (t = head; t->next; t = t->next); 2387a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger t->next = tree->child; 2397a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger count += flatten_tree(head, tree->child); 2407a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2417a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2427a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (tree->relation == 0) 2437a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger break; 2447a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2457a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger tree = tree->next; 2467a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2477a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2487a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (i = 0, t = head; t; t = t->next, i++) 2497a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger t->index = i; 2507a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2517a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (t = head; t; t = t->next) 2527a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (t->child) 2537a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger t->child_ref = t->child->index; 2547a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2557a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return count; 2567a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 2577a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2587a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerint em_parse_error(int err, struct bstr *args, struct bstr *carg, 2597a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct ematch_util *e, char *fmt, ...) 2607a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 2617a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger va_list a; 2627a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2637a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger va_start(a, fmt); 2647a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger vfprintf(stderr, fmt, a); 2657a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger va_end(a); 2667a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2677a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (ematch_err) 2687a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, ": %s\n... ", ematch_err); 2697a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger else 2707a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "\n... "); 2717a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2727a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger while (ematch_argc < begin_argc) { 2737a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (ematch_argc == (begin_argc - 1)) 2747a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, ">>%s<< ", *begin_argv); 2757a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger else 2767a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "%s ", *begin_argv); 2777a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger begin_argv++; 2787a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger begin_argc--; 2797a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2807a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2817a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "...\n"); 2827a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2837a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (args) { 2847a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "... %s(", e->kind); 2857a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger while (args) { 2867a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "%s", args == carg ? ">>" : ""); 2877a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger bstr_print(stderr, args, 1); 2887a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "%s%s", args == carg ? "<<" : "", 2897a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger args->next ? " " : ""); 2907a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger args = args->next; 2917a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2927a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, ")...\n"); 2937a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2947a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2957a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2967a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (e == NULL) { 2977a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, 2987a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger "Usage: EXPR\n" \ 2997a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger "where: EXPR := TERM [ { and | or } EXPR ]\n" \ 3007a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger " TERM := [ not ] { MATCH | '(' EXPR ')' }\n" \ 3017a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger " MATCH := module '(' ARGS ')'\n" \ 3027a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger " ARGS := ARG1 ARG2 ...\n" \ 3037a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger "\n" \ 3047a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger "Example: a(x y) and not (b(x) or c(x y z))\n"); 3057a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } else 3067a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger e->print_usage(stderr); 3077a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3087a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -err; 3097a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 3107a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3117a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic inline void free_ematch_err(void) 3127a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 3137a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (ematch_err) { 3147a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger free(ematch_err); 3157a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger ematch_err = NULL; 3167a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 3177a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 3187a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3197a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerextern int ematch_parse(void); 3207a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3217a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerint parse_ematch(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) 3227a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 3237a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger begin_argc = ematch_argc = *argc_p; 3247a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger begin_argv = ematch_argv = *argv_p; 3257a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3267a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (ematch_parse()) { 3277a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int err = em_parse_error(EINVAL, NULL, NULL, NULL, 3287a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger "Parse error"); 3297a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger free_ematch_err(); 3307a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return err; 3317a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 3327a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3337a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger free_ematch_err(); 3347a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3357a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger /* undo look ahead by parser */ 3367a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger ematch_argc++; 3377a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger ematch_argv--; 3387a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3397a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (ematch_root) { 3407a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct rtattr *tail, *tail_list; 3417a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3427a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct tcf_ematch_tree_hdr hdr = { 3437a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger .nmatches = flatten_tree(ematch_root, ematch_root), 3447a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger .progid = TCF_EM_PROG_TC 3457a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger }; 3467a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3477a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger tail = NLMSG_TAIL(n); 3487a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger addattr_l(n, MAX_MSG, tca_id, NULL, 0); 3497a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger addattr_l(n, MAX_MSG, TCA_EMATCH_TREE_HDR, &hdr, sizeof(hdr)); 3507a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3517a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger tail_list = NLMSG_TAIL(n); 3527a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger addattr_l(n, MAX_MSG, TCA_EMATCH_TREE_LIST, NULL, 0); 3537a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3547a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (parse_tree(n, ematch_root) < 0) 3557a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 3567a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3577a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger tail_list->rta_len = (void*) NLMSG_TAIL(n) - (void*) tail_list; 3587a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger tail->rta_len = (void*) NLMSG_TAIL(n) - (void*) tail; 3597a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 3607a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3617a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger *argc_p = ematch_argc; 3627a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger *argv_p = ematch_argv; 3637a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3647a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return 0; 3657a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 3667a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3677a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic int print_ematch_seq(FILE *fd, struct rtattr **tb, int start, 3687a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int prefix) 3697a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 3707a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int n, i = start; 3717a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct tcf_ematch_hdr *hdr; 3727a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int dlen; 3737a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger void *data; 3747a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3757a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (;;) { 3767a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (tb[i] == NULL) 3777a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 3787a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3797a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger dlen = RTA_PAYLOAD(tb[i]) - sizeof(*hdr); 3807a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger data = (void *) RTA_DATA(tb[i]) + sizeof(*hdr); 3817a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3827a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (dlen < 0) 3837a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 3847a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3857a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger hdr = RTA_DATA(tb[i]); 3867a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3877a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (hdr->flags & TCF_EM_INVERT) 3887a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, "NOT "); 3897a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3907a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (hdr->kind == 0) { 3917a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger __u32 ref; 3927a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3937a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (dlen < sizeof(__u32)) 3947a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 3957a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3967a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger ref = *(__u32 *) data; 3977a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, "(\n"); 3987a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (n = 0; n <= prefix; n++) 3997a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, " "); 4007a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (print_ematch_seq(fd, tb, ref + 1, prefix + 1) < 0) 4017a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 4027a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (n = 0; n < prefix; n++) 4037a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, " "); 4047a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, ") "); 4057a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4067a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } else { 4077a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct ematch_util *e; 4087a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4097a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger e = get_ematch_kind_num(hdr->kind); 4107a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (e == NULL) 4117a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, "[unknown ematch %d]\n", 4127a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger hdr->kind); 4137a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger else { 4147a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, "%s(", e->kind); 4157a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (e->print_eopt(fd, hdr, data, dlen) < 0) 4167a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 4177a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, ")\n"); 4187a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 4197a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (hdr->flags & TCF_EM_REL_MASK) 4207a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (n = 0; n < prefix; n++) 4217a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, " "); 4227a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 4237a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4247a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger switch (hdr->flags & TCF_EM_REL_MASK) { 4257a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger case TCF_EM_REL_AND: 4267a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, "AND "); 4277a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger break; 4287a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4297a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger case TCF_EM_REL_OR: 4307a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, "OR "); 4317a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger break; 4327a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4337a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger default: 4347a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return 0; 4357a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 4367a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4377a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger i++; 4387a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 4397a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4407a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return 0; 4417a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 4427a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4437a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic int print_ematch_list(FILE *fd, struct tcf_ematch_tree_hdr *hdr, 4447a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct rtattr *rta) 4457a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 4467a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int err = -1; 4477a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct rtattr **tb; 4487a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4497a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger tb = malloc((hdr->nmatches + 1) * sizeof(struct rtattr *)); 4507a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (tb == NULL) 4517a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 4527a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4537a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (parse_rtattr_nested(tb, hdr->nmatches, rta) < 0) 4547a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger goto errout; 4557a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4567a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, "\n "); 4577a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (print_ematch_seq(fd, tb, 1, 1) < 0) 4587a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger goto errout; 4597a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4607a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger err = 0; 4617a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingererrout: 4627a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger free(tb); 4637a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return err; 4647a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 4657a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4667a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerint print_ematch(FILE *fd, const struct rtattr *rta) 4677a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 4687a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct rtattr *tb[TCA_EMATCH_TREE_MAX+1]; 4697a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct tcf_ematch_tree_hdr *hdr; 4707a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4717a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (parse_rtattr_nested(tb, TCA_EMATCH_TREE_MAX, rta) < 0) 4727a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 4737a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4747a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (tb[TCA_EMATCH_TREE_HDR] == NULL) { 4757a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "Missing ematch tree header\n"); 4767a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 4777a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 4787a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4797a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (tb[TCA_EMATCH_TREE_LIST] == NULL) { 4807a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "Missing ematch tree list\n"); 4817a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 4827a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 4837a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4847a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (RTA_PAYLOAD(tb[TCA_EMATCH_TREE_HDR]) < sizeof(*hdr)) { 4857a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "Ematch tree header size mismatch\n"); 4867a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 4877a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 4887a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4897a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger hdr = RTA_DATA(tb[TCA_EMATCH_TREE_HDR]); 4907a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4917a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return print_ematch_list(fd, hdr, tb[TCA_EMATCH_TREE_LIST]); 4927a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 493