1#ifndef __TC_EMATCH_H_
2#define __TC_EMATCH_H_
3
4#include <ctype.h>
5#include <stdlib.h>
6#include <string.h>
7
8#include "utils.h"
9#include "tc_util.h"
10
11#define EMATCHKINDSIZ 16
12
13struct bstr
14{
15	char	*data;
16	unsigned int	len;
17	int		quoted;
18	struct bstr	*next;
19};
20
21static inline struct bstr * bstr_alloc(const char *text)
22{
23	struct bstr *b = calloc(1, sizeof(*b));
24
25	if (b == NULL)
26		return NULL;
27
28	b->data = strdup(text);
29	if (b->data == NULL) {
30		free(b);
31		return NULL;
32	}
33
34	b->len = strlen(text);
35
36	return b;
37}
38
39static inline struct bstr * bstr_new(char *data, unsigned int len)
40{
41	struct bstr *b = calloc(1, sizeof(*b));
42
43	if (b == NULL)
44		return NULL;
45
46	b->data = data;
47	b->len = len;
48
49	return b;
50}
51
52static inline int bstrcmp(struct bstr *b, const char *text)
53{
54	int len = strlen(text);
55	int d = b->len - len;
56
57	if (d == 0)
58		return strncmp(b->data, text, len);
59
60	return d;
61}
62
63static inline unsigned long bstrtoul(struct bstr *b)
64{
65	char *inv = NULL;
66	unsigned long l;
67	char buf[b->len+1];
68
69	memcpy(buf, b->data, b->len);
70	buf[b->len] = '\0';
71
72	l = strtol(buf, &inv, 0);
73	if (l == ULONG_MAX || inv == buf)
74		return LONG_MAX;
75
76	return l;
77}
78
79static inline void bstr_print(FILE *fd, struct bstr *b, int ascii)
80{
81	int i;
82	char *s = b->data;
83
84	if (ascii)
85		for (i = 0; i < b->len; i++)
86		    fprintf(fd, "%c", isprint(s[i]) ? s[i] : '.');
87	else {
88		for (i = 0; i < b->len; i++)
89		    fprintf(fd, "%02x", s[i]);
90		fprintf(fd, "\"");
91		for (i = 0; i < b->len; i++)
92		    fprintf(fd, "%c", isprint(s[i]) ? s[i] : '.');
93		fprintf(fd, "\"");
94	}
95}
96
97static inline struct bstr *bstr_next(struct bstr *b)
98{
99	return b->next;
100}
101
102struct ematch
103{
104	struct bstr	*args;
105	int		index;
106	int		inverted;
107	int		relation;
108	int		child_ref;
109	struct ematch	*child;
110	struct ematch	*next;
111};
112
113static inline struct ematch * new_ematch(struct bstr *args, int inverted)
114{
115	struct ematch *e = calloc(1, sizeof(*e));
116
117	if (e == NULL)
118		return NULL;
119
120	e->args = args;
121	e->inverted = inverted;
122
123	return e;
124}
125
126static inline void print_ematch_tree(struct ematch *tree)
127{
128	struct ematch *t;
129
130	for (t = tree; t; t = t->next) {
131		if (t->inverted)
132			printf("NOT ");
133
134		if (t->child) {
135			printf("(");
136			print_ematch_tree(t->child);
137			printf(")");
138		} else {
139			struct bstr *b;
140			for (b = t->args; b; b = b->next)
141				printf("%s%s", b->data, b->next ? " " : "");
142		}
143
144		if (t->relation == TCF_EM_REL_AND)
145			printf(" AND ");
146		else if (t->relation == TCF_EM_REL_OR)
147			printf(" OR ");
148	}
149}
150
151struct ematch_util
152{
153	char			kind[EMATCHKINDSIZ];
154	int			kind_num;
155	int	(*parse_eopt)(struct nlmsghdr *,struct tcf_ematch_hdr *,
156			      struct bstr *);
157	int	(*print_eopt)(FILE *, struct tcf_ematch_hdr *, void *, int);
158	void	(*print_usage)(FILE *);
159	struct ematch_util	*next;
160};
161
162static inline int parse_layer(struct bstr *b)
163{
164	if (*((char *) b->data) == 'l')
165		return TCF_LAYER_LINK;
166	else if (*((char *) b->data) == 'n')
167		return TCF_LAYER_NETWORK;
168	else if (*((char *) b->data) == 't')
169		return TCF_LAYER_TRANSPORT;
170	else
171		return INT_MAX;
172}
173
174extern int em_parse_error(int err, struct bstr *args, struct bstr *carg,
175		   struct ematch_util *, char *fmt, ...);
176extern int print_ematch(FILE *, const struct rtattr *);
177extern int parse_ematch(int *, char ***, int, struct nlmsghdr *);
178
179#endif
180