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" \ 48ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger "\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; 69ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 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; 107ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 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; 123f332d169246447bd5e258ac03d5ee840a70adb1eshemminger *dst = 0; 1247a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerout: 1257a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fclose(fd); 1267a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return err; 1277a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 1287a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1297a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic struct ematch_util *get_ematch_kind(char *kind) 1307a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 1317a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger static void *body; 1327a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger void *dlh; 1337a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger char buf[256]; 1347a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct ematch_util *e; 1357a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1367a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (e = ematch_list; e; e = e->next) { 1377a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (strcmp(e->kind, kind) == 0) 1387a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return e; 1397a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 1407a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1417a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger snprintf(buf, sizeof(buf), "em_%s.so", kind); 1427a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger dlh = dlopen(buf, RTLD_LAZY); 1437a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (dlh == NULL) { 1447a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger dlh = body; 1457a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (dlh == NULL) { 1467a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger dlh = body = dlopen(NULL, RTLD_LAZY); 1477a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (dlh == NULL) 1487a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return NULL; 1497a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 1507a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 1517a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1527a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger snprintf(buf, sizeof(buf), "%s_ematch_util", kind); 1537a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger e = dlsym(dlh, buf); 1547a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (e == NULL) 1557a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return NULL; 1567a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1577a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger e->next = ematch_list; 1587a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger ematch_list = e; 1597a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1607a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return e; 1617a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 1627a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1637a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic struct ematch_util *get_ematch_kind_num(__u16 kind) 1647a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 1657a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger char name[32]; 1667a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1677a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (lookup_map(kind, name, sizeof(name), EMATCH_MAP) < 0) 1687a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return NULL; 1697a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1707a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return get_ematch_kind(name); 1717a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 1727a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1737a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic int parse_tree(struct nlmsghdr *n, struct ematch *tree) 1747a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 1757a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int index = 1; 1767a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct ematch *t; 1777a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1787a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (t = tree; t; t = t->next) { 1797a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct rtattr *tail = NLMSG_TAIL(n); 1807a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct tcf_ematch_hdr hdr = { 1817a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger .flags = t->relation 1827a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger }; 1837a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1847a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (t->inverted) 1857a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger hdr.flags |= TCF_EM_INVERT; 186ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 1877a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger addattr_l(n, MAX_MSG, index++, NULL, 0); 1887a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1897a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (t->child) { 1907a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger __u32 r = t->child_ref; 1917a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger addraw_l(n, MAX_MSG, &hdr, sizeof(hdr)); 1927a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger addraw_l(n, MAX_MSG, &r, sizeof(r)); 1937a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } else { 1943fcdebb6d0b6f7cafb0a21e5e892d3670326dc9ashemminger int num = 0, err; 1957a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger char buf[64]; 1967a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct ematch_util *e; 1977a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 1987a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (t->args == NULL) 1997a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 2007a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2017a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger strncpy(buf, (char*) t->args->data, sizeof(buf)-1); 2027a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger e = get_ematch_kind(buf); 2037a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (e == NULL) { 2047a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "Unknown ematch \"%s\"\n", 2057a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger buf); 2067a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 2077a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2087a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2097a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger err = lookup_map_id(buf, &num, EMATCH_MAP); 2107a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (err < 0) { 2117a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (err == -ENOENT) 2127a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger map_warning(e->kind_num, buf); 2137a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return err; 2147a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2157a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2167a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger hdr.kind = num; 2177a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (e->parse_eopt(n, &hdr, t->args->next) < 0) 2187a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 2197a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2207a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2217a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger tail->rta_len = (void*) NLMSG_TAIL(n) - (void*) tail; 2227a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2237a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2247a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return 0; 2257a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 2267a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2277a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic int flatten_tree(struct ematch *head, struct ematch *tree) 2287a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 2297a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int i, count = 0; 2307a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct ematch *t; 2317a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2327a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (;;) { 2337a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger count++; 2347a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2357a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (tree->child) { 2367a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (t = head; t->next; t = t->next); 2377a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger t->next = tree->child; 2387a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger count += flatten_tree(head, tree->child); 2397a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2407a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2417a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (tree->relation == 0) 2427a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger break; 2437a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2447a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger tree = tree->next; 2457a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2467a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2477a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (i = 0, t = head; t; t = t->next, i++) 2487a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger t->index = i; 2497a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2507a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (t = head; t; t = t->next) 2517a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (t->child) 2527a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger t->child_ref = t->child->index; 2537a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2547a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return count; 2557a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 2567a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2577a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerint em_parse_error(int err, struct bstr *args, struct bstr *carg, 2587a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct ematch_util *e, char *fmt, ...) 2597a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 2607a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger va_list a; 2617a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2627a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger va_start(a, fmt); 2637a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger vfprintf(stderr, fmt, a); 2647a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger va_end(a); 2657a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2667a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (ematch_err) 2677a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, ": %s\n... ", ematch_err); 2687a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger else 2697a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "\n... "); 2707a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2717a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger while (ematch_argc < begin_argc) { 2727a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (ematch_argc == (begin_argc - 1)) 2737a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, ">>%s<< ", *begin_argv); 2747a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger else 2757a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "%s ", *begin_argv); 2767a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger begin_argv++; 2777a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger begin_argc--; 2787a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 279ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 2807a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "...\n"); 2817a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2827a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (args) { 2837a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "... %s(", e->kind); 2847a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger while (args) { 2857a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "%s", args == carg ? ">>" : ""); 2867a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger bstr_print(stderr, args, 1); 2877a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "%s%s", args == carg ? "<<" : "", 2887a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger args->next ? " " : ""); 2897a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger args = args->next; 2907a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2917a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, ")...\n"); 2927a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2937a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 2947a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 2957a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (e == NULL) { 2967a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, 2977a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger "Usage: EXPR\n" \ 2987a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger "where: EXPR := TERM [ { and | or } EXPR ]\n" \ 2997a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger " TERM := [ not ] { MATCH | '(' EXPR ')' }\n" \ 3007a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger " MATCH := module '(' ARGS ')'\n" \ 3017a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger " ARGS := ARG1 ARG2 ...\n" \ 3027a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger "\n" \ 3037a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger "Example: a(x y) and not (b(x) or c(x y z))\n"); 3047a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } else 3057a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger e->print_usage(stderr); 3067a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3077a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -err; 3087a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 3097a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3107a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic inline void free_ematch_err(void) 3117a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 3127a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (ematch_err) { 3137a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger free(ematch_err); 3147a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger ematch_err = NULL; 3157a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 3167a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 3177a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3187a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerextern int ematch_parse(void); 3197a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3207a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerint parse_ematch(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) 3217a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 3227a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger begin_argc = ematch_argc = *argc_p; 3237a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger begin_argv = ematch_argv = *argv_p; 3247a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3257a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (ematch_parse()) { 3267a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int err = em_parse_error(EINVAL, NULL, NULL, NULL, 3277a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger "Parse error"); 3287a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger free_ematch_err(); 3297a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return err; 3307a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 3317a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3327a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger free_ematch_err(); 3337a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3347a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger /* undo look ahead by parser */ 3357a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger ematch_argc++; 3367a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger ematch_argv--; 3377a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3387a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (ematch_root) { 3397a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct rtattr *tail, *tail_list; 3407a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3417a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct tcf_ematch_tree_hdr hdr = { 3427a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger .nmatches = flatten_tree(ematch_root, ematch_root), 3437a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger .progid = TCF_EM_PROG_TC 3447a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger }; 3457a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3467a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger tail = NLMSG_TAIL(n); 3477a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger addattr_l(n, MAX_MSG, tca_id, NULL, 0); 3487a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger addattr_l(n, MAX_MSG, TCA_EMATCH_TREE_HDR, &hdr, sizeof(hdr)); 3497a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3507a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger tail_list = NLMSG_TAIL(n); 3517a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger addattr_l(n, MAX_MSG, TCA_EMATCH_TREE_LIST, NULL, 0); 3527a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3537a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (parse_tree(n, ematch_root) < 0) 3547a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 3557a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3567a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger tail_list->rta_len = (void*) NLMSG_TAIL(n) - (void*) tail_list; 3577a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger tail->rta_len = (void*) NLMSG_TAIL(n) - (void*) tail; 3587a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 3597a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3607a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger *argc_p = ematch_argc; 3617a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger *argv_p = ematch_argv; 3627a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3637a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return 0; 3647a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 3657a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3667a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic int print_ematch_seq(FILE *fd, struct rtattr **tb, int start, 3677a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int prefix) 3687a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 3697a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int n, i = start; 3707a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct tcf_ematch_hdr *hdr; 3717a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int dlen; 3727a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger void *data; 3737a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3747a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (;;) { 3757a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (tb[i] == NULL) 3767a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 3777a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3787a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger dlen = RTA_PAYLOAD(tb[i]) - sizeof(*hdr); 3797a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger data = (void *) RTA_DATA(tb[i]) + sizeof(*hdr); 3807a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3817a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (dlen < 0) 3827a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 3837a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3847a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger hdr = RTA_DATA(tb[i]); 3857a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3867a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (hdr->flags & TCF_EM_INVERT) 3877a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, "NOT "); 3887a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3897a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (hdr->kind == 0) { 3907a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger __u32 ref; 3917a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3927a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (dlen < sizeof(__u32)) 3937a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 3947a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 3957a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger ref = *(__u32 *) data; 3967a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, "(\n"); 3977a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (n = 0; n <= prefix; n++) 3987a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, " "); 3997a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (print_ematch_seq(fd, tb, ref + 1, prefix + 1) < 0) 4007a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 4017a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (n = 0; n < prefix; n++) 4027a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, " "); 4037a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, ") "); 4047a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4057a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } else { 4067a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct ematch_util *e; 4077a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4087a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger e = get_ematch_kind_num(hdr->kind); 4097a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (e == NULL) 4107a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, "[unknown ematch %d]\n", 4117a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger hdr->kind); 4127a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger else { 4137a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, "%s(", e->kind); 4147a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (e->print_eopt(fd, hdr, data, dlen) < 0) 4157a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 4167a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, ")\n"); 4177a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 4187a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (hdr->flags & TCF_EM_REL_MASK) 4197a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger for (n = 0; n < prefix; n++) 4207a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, " "); 4217a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 4227a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4237a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger switch (hdr->flags & TCF_EM_REL_MASK) { 4247a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger case TCF_EM_REL_AND: 4257a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, "AND "); 4267a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger break; 4277a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4287a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger case TCF_EM_REL_OR: 4297a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(fd, "OR "); 4307a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger break; 4317a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4327a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger default: 4337a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return 0; 4347a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 4357a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4367a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger i++; 4377a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 438ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger 4397a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return 0; 4407a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 4417a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4427a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerstatic int print_ematch_list(FILE *fd, struct tcf_ematch_tree_hdr *hdr, 4437a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct rtattr *rta) 4447a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 4457a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger int err = -1; 4467a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct rtattr **tb; 4477a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4487a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger tb = malloc((hdr->nmatches + 1) * sizeof(struct rtattr *)); 4497a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (tb == NULL) 4507a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 4517a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4524b45abd1f000f62df9b624e393d9f3d62751a266Stephen Hemminger if (hdr->nmatches > 0) { 4534b45abd1f000f62df9b624e393d9f3d62751a266Stephen Hemminger if (parse_rtattr_nested(tb, hdr->nmatches, rta) < 0) 4544b45abd1f000f62df9b624e393d9f3d62751a266Stephen Hemminger goto errout; 4557a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4564b45abd1f000f62df9b624e393d9f3d62751a266Stephen Hemminger fprintf(fd, "\n "); 4574b45abd1f000f62df9b624e393d9f3d62751a266Stephen Hemminger if (print_ematch_seq(fd, tb, 1, 1) < 0) 4584b45abd1f000f62df9b624e393d9f3d62751a266Stephen Hemminger goto errout; 4594b45abd1f000f62df9b624e393d9f3d62751a266Stephen Hemminger } 4607a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4617a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger err = 0; 4627a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingererrout: 4637a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger free(tb); 4647a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return err; 4657a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 4667a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4677a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemmingerint print_ematch(FILE *fd, const struct rtattr *rta) 4687a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger{ 4697a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct rtattr *tb[TCA_EMATCH_TREE_MAX+1]; 4707a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger struct tcf_ematch_tree_hdr *hdr; 4717a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4727a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (parse_rtattr_nested(tb, TCA_EMATCH_TREE_MAX, rta) < 0) 4737a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 4747a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4757a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (tb[TCA_EMATCH_TREE_HDR] == NULL) { 4767a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "Missing ematch tree header\n"); 4777a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 4787a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 4797a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4807a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (tb[TCA_EMATCH_TREE_LIST] == NULL) { 4817a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "Missing ematch tree list\n"); 4827a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 4837a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 4847a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4857a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger if (RTA_PAYLOAD(tb[TCA_EMATCH_TREE_HDR]) < sizeof(*hdr)) { 4867a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger fprintf(stderr, "Ematch tree header size mismatch\n"); 4877a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return -1; 4887a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger } 4897a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4907a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger hdr = RTA_DATA(tb[TCA_EMATCH_TREE_HDR]); 4917a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger 4927a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger return print_ematch_list(fd, hdr, tb[TCA_EMATCH_TREE_LIST]); 4937a473c77e613e4174dff0585d5c0f4f1cd9a21eeshemminger} 494b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 495b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemmingerstruct bstr * bstr_alloc(const char *text) 496b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger{ 497b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger struct bstr *b = calloc(1, sizeof(*b)); 498b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 499b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger if (b == NULL) 500b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger return NULL; 501b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 502b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger b->data = strdup(text); 503b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger if (b->data == NULL) { 504b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger free(b); 505b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger return NULL; 506b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger } 507b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 508b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger b->len = strlen(text); 509b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 510b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger return b; 511b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger} 512b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 513b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemmingerunsigned long bstrtoul(const struct bstr *b) 514b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger{ 515b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger char *inv = NULL; 516b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger unsigned long l; 517b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger char buf[b->len+1]; 518b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 519b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger memcpy(buf, b->data, b->len); 520b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger buf[b->len] = '\0'; 521b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 522b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger l = strtoul(buf, &inv, 0); 523b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger if (l == ULONG_MAX || inv == buf) 524b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger return ULONG_MAX; 525b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 526b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger return l; 527b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger} 528b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 529b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemmingervoid bstr_print(FILE *fd, const struct bstr *b, int ascii) 530b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger{ 531b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger int i; 532b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger char *s = b->data; 533b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 534b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger if (ascii) 535b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger for (i = 0; i < b->len; i++) 536b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger fprintf(fd, "%c", isprint(s[i]) ? s[i] : '.'); 537b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger else { 538b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger for (i = 0; i < b->len; i++) 539b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger fprintf(fd, "%02x", s[i]); 540b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger fprintf(fd, "\""); 541b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger for (i = 0; i < b->len; i++) 542b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger fprintf(fd, "%c", isprint(s[i]) ? s[i] : '.'); 543b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger fprintf(fd, "\""); 544b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger } 545b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger} 546b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 547b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemmingervoid print_ematch_tree(const struct ematch *tree) 548b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger{ 549b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger const struct ematch *t; 550b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 551b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger for (t = tree; t; t = t->next) { 552b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger if (t->inverted) 553b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger printf("NOT "); 554b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 555b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger if (t->child) { 556b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger printf("("); 557b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger print_ematch_tree(t->child); 558b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger printf(")"); 559b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger } else { 560b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger struct bstr *b; 561b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger for (b = t->args; b; b = b->next) 562b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger printf("%s%s", b->data, b->next ? " " : ""); 563b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger } 564b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger 565b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger if (t->relation == TCF_EM_REL_AND) 566b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger printf(" AND "); 567b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger else if (t->relation == TCF_EM_REL_OR) 568b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger printf(" OR "); 569b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger } 570b6da1afc736b7ab7fcd3b4df4f4486525c1ab7d3Stephen Hemminger} 571