#ifndef __TC_EMATCH_H_ #define __TC_EMATCH_H_ #include #include #include #include "utils.h" #include "tc_util.h" #define EMATCHKINDSIZ 16 struct bstr { char *data; unsigned int len; int quoted; struct bstr *next; }; static inline struct bstr * bstr_alloc(const char *text) { struct bstr *b = calloc(1, sizeof(*b)); if (b == NULL) return NULL; b->data = strdup(text); if (b->data == NULL) { free(b); return NULL; } b->len = strlen(text); return b; } static inline struct bstr * bstr_new(char *data, unsigned int len) { struct bstr *b = calloc(1, sizeof(*b)); if (b == NULL) return NULL; b->data = data; b->len = len; return b; } static inline int bstrcmp(struct bstr *b, const char *text) { int len = strlen(text); int d = b->len - len; if (d == 0) return strncmp(b->data, text, len); return d; } static inline unsigned long bstrtoul(struct bstr *b) { char *inv = NULL; unsigned long l; char buf[b->len+1]; memcpy(buf, b->data, b->len); buf[b->len] = '\0'; l = strtol(buf, &inv, 0); if (l == ULONG_MAX || inv == buf) return LONG_MAX; return l; } static inline void bstr_print(FILE *fd, struct bstr *b, int ascii) { int i; char *s = b->data; if (ascii) for (i = 0; i < b->len; i++) fprintf(fd, "%c", isprint(s[i]) ? s[i] : '.'); else { for (i = 0; i < b->len; i++) fprintf(fd, "%02x", s[i]); fprintf(fd, "\""); for (i = 0; i < b->len; i++) fprintf(fd, "%c", isprint(s[i]) ? s[i] : '.'); fprintf(fd, "\""); } } static inline struct bstr *bstr_next(struct bstr *b) { return b->next; } struct ematch { struct bstr *args; int index; int inverted; int relation; int child_ref; struct ematch *child; struct ematch *next; }; static inline struct ematch * new_ematch(struct bstr *args, int inverted) { struct ematch *e = calloc(1, sizeof(*e)); if (e == NULL) return NULL; e->args = args; e->inverted = inverted; return e; } static inline void print_ematch_tree(struct ematch *tree) { struct ematch *t; for (t = tree; t; t = t->next) { if (t->inverted) printf("NOT "); if (t->child) { printf("("); print_ematch_tree(t->child); printf(")"); } else { struct bstr *b; for (b = t->args; b; b = b->next) printf("%s%s", b->data, b->next ? " " : ""); } if (t->relation == TCF_EM_REL_AND) printf(" AND "); else if (t->relation == TCF_EM_REL_OR) printf(" OR "); } } struct ematch_util { char kind[EMATCHKINDSIZ]; int kind_num; int (*parse_eopt)(struct nlmsghdr *,struct tcf_ematch_hdr *, struct bstr *); int (*print_eopt)(FILE *, struct tcf_ematch_hdr *, void *, int); void (*print_usage)(FILE *); struct ematch_util *next; }; static inline int parse_layer(struct bstr *b) { if (*((char *) b->data) == 'l') return TCF_LAYER_LINK; else if (*((char *) b->data) == 'n') return TCF_LAYER_NETWORK; else if (*((char *) b->data) == 't') return TCF_LAYER_TRANSPORT; else return INT_MAX; } extern int em_parse_error(int err, struct bstr *args, struct bstr *carg, struct ematch_util *, char *fmt, ...); extern int print_ematch(FILE *, const struct rtattr *); extern int parse_ematch(int *, char ***, int, struct nlmsghdr *); #endif