]>
git.proxmox.com Git - mirror_iproute2.git/blob - tc/m_ematch.c
2 * m_ematch.c Extended Matches
4 * This program is free software; you can distribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Thomas Graf <tgraf@suug.ch>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
29 #define EMATCH_MAP "/etc/iproute2/ematch_map"
31 static struct ematch_util
*ematch_list
;
33 /* export to bison parser */
36 char *ematch_err
= NULL
;
37 struct ematch
*ematch_root
;
39 static int begin_argc
;
40 static char **begin_argv
;
42 static inline void map_warning(int num
, char *kind
)
45 "Error: Unable to find ematch \"%s\" in %s\n" \
46 "Please assign a unique ID to the ematch kind the suggested " \
49 kind
, EMATCH_MAP
, num
, kind
);
52 static int lookup_map(__u16 num
, char *dst
, int len
, const char *file
)
56 FILE *fd
= fopen(file
, "r");
61 while (fgets(buf
, sizeof(buf
), fd
)) {
62 char namebuf
[512], *p
= buf
;
65 while (*p
== ' ' || *p
== '\t')
67 if (*p
== '#' || *p
== '\n' || *p
== 0)
70 if (sscanf(p
, "%d %s", &id
, namebuf
) != 2) {
71 fprintf(stderr
, "ematch map %s corrupted at %s\n",
78 strncpy(dst
, namebuf
, len
- 1);
90 static int lookup_map_id(char *kind
, int *dst
, const char *file
)
94 FILE *fd
= fopen(file
, "r");
99 while (fgets(buf
, sizeof(buf
), fd
)) {
100 char namebuf
[512], *p
= buf
;
103 while (*p
== ' ' || *p
== '\t')
105 if (*p
== '#' || *p
== '\n' || *p
== 0)
108 if (sscanf(p
, "%d %s", &id
, namebuf
) != 2) {
109 fprintf(stderr
, "ematch map %s corrupted at %s\n",
114 if (!strcasecmp(namebuf
, kind
)) {
129 static struct ematch_util
*get_ematch_kind(char *kind
)
134 struct ematch_util
*e
;
136 for (e
= ematch_list
; e
; e
= e
->next
) {
137 if (strcmp(e
->kind
, kind
) == 0)
141 snprintf(buf
, sizeof(buf
), "em_%s.so", kind
);
142 dlh
= dlopen(buf
, RTLD_LAZY
);
146 dlh
= body
= dlopen(NULL
, RTLD_LAZY
);
152 snprintf(buf
, sizeof(buf
), "%s_ematch_util", kind
);
157 e
->next
= ematch_list
;
163 static struct ematch_util
*get_ematch_kind_num(__u16 kind
)
167 if (lookup_map(kind
, name
, sizeof(name
), EMATCH_MAP
) < 0)
170 return get_ematch_kind(name
);
175 static int parse_tree(struct nlmsghdr
*n
, struct ematch
*tree
)
180 for (t
= tree
; t
; t
= t
->next
) {
181 struct rtattr
*tail
= NLMSG_TAIL(n
);
182 struct tcf_ematch_hdr hdr
= {
187 hdr
.flags
|= TCF_EM_INVERT
;
189 addattr_l(n
, MAX_MSG
, index
++, NULL
, 0);
192 __u32 r
= t
->child_ref
;
193 addraw_l(n
, MAX_MSG
, &hdr
, sizeof(hdr
));
194 addraw_l(n
, MAX_MSG
, &r
, sizeof(r
));
198 struct ematch_util
*e
;
203 strncpy(buf
, (char*) t
->args
->data
, sizeof(buf
)-1);
204 e
= get_ematch_kind(buf
);
206 fprintf(stderr
, "Unknown ematch \"%s\"\n",
211 err
= lookup_map_id(buf
, &num
, EMATCH_MAP
);
214 map_warning(e
->kind_num
, buf
);
219 if (e
->parse_eopt(n
, &hdr
, t
->args
->next
) < 0)
223 tail
->rta_len
= (void*) NLMSG_TAIL(n
) - (void*) tail
;
229 static int flatten_tree(struct ematch
*head
, struct ematch
*tree
)
238 for (t
= head
; t
->next
; t
= t
->next
);
239 t
->next
= tree
->child
;
240 count
+= flatten_tree(head
, tree
->child
);
243 if (tree
->relation
== 0)
249 for (i
= 0, t
= head
; t
; t
= t
->next
, i
++)
252 for (t
= head
; t
; t
= t
->next
)
254 t
->child_ref
= t
->child
->index
;
259 int em_parse_error(int err
, struct bstr
*args
, struct bstr
*carg
,
260 struct ematch_util
*e
, char *fmt
, ...)
265 vfprintf(stderr
, fmt
, a
);
269 fprintf(stderr
, ": %s\n... ", ematch_err
);
271 fprintf(stderr
, "\n... ");
273 while (ematch_argc
< begin_argc
) {
274 if (ematch_argc
== (begin_argc
- 1))
275 fprintf(stderr
, ">>%s<< ", *begin_argv
);
277 fprintf(stderr
, "%s ", *begin_argv
);
282 fprintf(stderr
, "...\n");
285 fprintf(stderr
, "... %s(", e
->kind
);
287 fprintf(stderr
, "%s", args
== carg
? ">>" : "");
288 bstr_print(stderr
, args
, 1);
289 fprintf(stderr
, "%s%s", args
== carg
? "<<" : "",
290 args
->next
? " " : "");
293 fprintf(stderr
, ")...\n");
300 "where: EXPR := TERM [ { and | or } EXPR ]\n" \
301 " TERM := [ not ] { MATCH | '(' EXPR ')' }\n" \
302 " MATCH := module '(' ARGS ')'\n" \
303 " ARGS := ARG1 ARG2 ...\n" \
305 "Example: a(x y) and not (b(x) or c(x y z))\n");
307 e
->print_usage(stderr
);
312 static inline void free_ematch_err(void)
320 extern int ematch_parse(void);
322 int parse_ematch(int *argc_p
, char ***argv_p
, int tca_id
, struct nlmsghdr
*n
)
324 begin_argc
= ematch_argc
= *argc_p
;
325 begin_argv
= ematch_argv
= *argv_p
;
327 if (ematch_parse()) {
328 int err
= em_parse_error(EINVAL
, NULL
, NULL
, NULL
,
336 /* undo look ahead by parser */
341 struct rtattr
*tail
, *tail_list
;
343 struct tcf_ematch_tree_hdr hdr
= {
344 .nmatches
= flatten_tree(ematch_root
, ematch_root
),
345 .progid
= TCF_EM_PROG_TC
348 tail
= NLMSG_TAIL(n
);
349 addattr_l(n
, MAX_MSG
, tca_id
, NULL
, 0);
350 addattr_l(n
, MAX_MSG
, TCA_EMATCH_TREE_HDR
, &hdr
, sizeof(hdr
));
352 tail_list
= NLMSG_TAIL(n
);
353 addattr_l(n
, MAX_MSG
, TCA_EMATCH_TREE_LIST
, NULL
, 0);
355 if (parse_tree(n
, ematch_root
) < 0)
358 tail_list
->rta_len
= (void*) NLMSG_TAIL(n
) - (void*) tail_list
;
359 tail
->rta_len
= (void*) NLMSG_TAIL(n
) - (void*) tail
;
362 *argc_p
= ematch_argc
;
363 *argv_p
= ematch_argv
;
368 static int print_ematch_seq(FILE *fd
, struct rtattr
**tb
, int start
,
372 struct tcf_ematch_hdr
*hdr
;
380 dlen
= RTA_PAYLOAD(tb
[i
]) - sizeof(*hdr
);
381 data
= (void *) RTA_DATA(tb
[i
]) + sizeof(*hdr
);
386 hdr
= RTA_DATA(tb
[i
]);
388 if (hdr
->flags
& TCF_EM_INVERT
)
391 if (hdr
->kind
== 0) {
394 if (dlen
< sizeof(__u32
))
397 ref
= *(__u32
*) data
;
399 for (n
= 0; n
<= prefix
; n
++)
401 if (print_ematch_seq(fd
, tb
, ref
+ 1, prefix
+ 1) < 0)
403 for (n
= 0; n
< prefix
; n
++)
408 struct ematch_util
*e
;
410 e
= get_ematch_kind_num(hdr
->kind
);
412 fprintf(fd
, "[unknown ematch %d]\n",
415 fprintf(fd
, "%s(", e
->kind
);
416 if (e
->print_eopt(fd
, hdr
, data
, dlen
) < 0)
420 if (hdr
->flags
& TCF_EM_REL_MASK
)
421 for (n
= 0; n
< prefix
; n
++)
425 switch (hdr
->flags
& TCF_EM_REL_MASK
) {
444 static int print_ematch_list(FILE *fd
, struct tcf_ematch_tree_hdr
*hdr
,
450 tb
= malloc((hdr
->nmatches
+ 1) * sizeof(struct rtattr
*));
454 if (parse_rtattr_nested(tb
, hdr
->nmatches
, rta
) < 0)
458 if (print_ematch_seq(fd
, tb
, 1, 1) < 0)
467 int print_ematch(FILE *fd
, const struct rtattr
*rta
)
469 struct rtattr
*tb
[TCA_EMATCH_TREE_MAX
+1];
470 struct tcf_ematch_tree_hdr
*hdr
;
472 if (parse_rtattr_nested(tb
, TCA_EMATCH_TREE_MAX
, rta
) < 0)
475 if (tb
[TCA_EMATCH_TREE_HDR
] == NULL
) {
476 fprintf(stderr
, "Missing ematch tree header\n");
480 if (tb
[TCA_EMATCH_TREE_LIST
] == NULL
) {
481 fprintf(stderr
, "Missing ematch tree list\n");
485 if (RTA_PAYLOAD(tb
[TCA_EMATCH_TREE_HDR
]) < sizeof(*hdr
)) {
486 fprintf(stderr
, "Ematch tree header size mismatch\n");
490 hdr
= RTA_DATA(tb
[TCA_EMATCH_TREE_HDR
]);
492 return print_ematch_list(fd
, hdr
, tb
[TCA_EMATCH_TREE_LIST
]);