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