diff options
author | Thomas Graf <tgr@lsx.localdomain> | 2009-09-02 18:31:14 +0200 |
---|---|---|
committer | Thomas Graf <tgr@lsx.localdomain> | 2009-09-02 18:31:14 +0200 |
commit | ef858fb492dfe98e3ae194264fbc73649cf8493a (patch) | |
tree | 86e6c7adc5f4ba2294cb31a386c3f8d90c8b88be /src | |
parent | 7d249fc2e1d0cb06cd4a4dfcc0a3c425ce63def7 (diff) | |
download | android_external_libnl-ef858fb492dfe98e3ae194264fbc73649cf8493a.tar.gz android_external_libnl-ef858fb492dfe98e3ae194264fbc73649cf8493a.tar.bz2 android_external_libnl-ef858fb492dfe98e3ae194264fbc73649cf8493a.zip |
- Reworked the classifier interface.
- Added initial ematch support
- Added support for the basic classifier
- Added support for the cgroup classifier
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 4 | ||||
-rw-r--r-- | src/cls/basic.c | 90 | ||||
-rw-r--r-- | src/cls/cgroup.c | 78 | ||||
-rw-r--r-- | src/cls/utils.c | 105 | ||||
-rw-r--r-- | src/cls/utils.h | 51 | ||||
-rw-r--r-- | src/nl-cls-add.c | 117 | ||||
-rw-r--r-- | src/nl-cls-delete.c | 133 | ||||
-rw-r--r-- | src/nl-cls-list.c | 113 | ||||
-rw-r--r-- | src/nl-list-caches.c | 2 | ||||
-rw-r--r-- | src/utils.h | 9 |
10 files changed, 701 insertions, 1 deletions
diff --git a/src/Makefile b/src/Makefile index 6a7bfd2..fb6ae9c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -17,6 +17,9 @@ LDFLAGS += -L../lib -lnl CIN := $(wildcard nl-*.c) $(wildcard genl-*.c) $(wildcard nf-*.c) TOOLS := $(CIN:%.c=%) +CLS := $(wildcard cls/*.c) +CLS_OBJ := $(CLS:%.c=%.o) + all: $(TOOLS) $(TOOLS): utils.o @@ -31,6 +34,7 @@ nl-rule-list: rule-utils.o rtnl-utils.o nl-neightbl-list: rtnl-utils.o nl-monitor: rtnl-utils.o nl-tctree-list: rtnl-utils.o +nl-cls-add nl-cls-delete nl-cls-list: rtnl-utils.o cls/utils.o $(CLS_OBJ) genl-ctrl-list: ctrl-utils.o diff --git a/src/cls/basic.c b/src/cls/basic.c new file mode 100644 index 0000000..df1c112 --- /dev/null +++ b/src/cls/basic.c @@ -0,0 +1,90 @@ +/* + * src/cls/basic.c Basic Classifier + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2 of the License. + * + * Copyright (c) 2008 Thomas Graf <tgraf@suug.ch> + */ + +#include "utils.h" +#include <netlink/route/cls/basic.h> +#include <netlink/route/cls/ematch.h> + +static void print_usage(void) +{ + printf( +"Usage: ... basic [OPTIONS]...\n" +"\n" +"Options\n" +" -h, --help Show this help.\n" +" -e, --ematch=MATCH Extended match (See --ematch help).\n" +" -c, --classid=HANDLE Target class to classify matching packets to.\n" + ); + exit(0); +} + +static void basic_parse_argv(struct rtnl_cls *cls, int argc, char **argv) +{ + uint32_t classid; + + for (;;) { + int c, optidx = 0, err; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "ematch", 1, 0, 'e' }, + { "classid", 1, 0, 'c' }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "he:c:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case '?': + exit(NLE_INVAL); + + case 'h': + print_usage(); + + case 'e': +#if 0 + if ((err = parse_ematch_syntax(optarg, &tree)) < 0) + fatal(err, "Error while parsing ematch: %s", + nl_geterror(err)); + + if ((err = rtnl_basic_set_ematch(cls, tree)) < 0) + fatal(err, "Unable to set ematch: %s", + nl_geterror(err)); +#endif + break; + + case 'c': + if ((err = rtnl_tc_str2handle(optarg, &classid)) < 0) + fatal(err, "Invalid classid \"%s\": %s", + optarg, nl_geterror(err)); + + if ((err = rtnl_basic_set_classid(cls, classid)) < 0) + fatal(err, "Unable to set classid: %s", + nl_geterror(err)); + break; + } + } +} + +static struct cls_module basic_module = { + .name = "basic", + .parse_argv = basic_parse_argv, +}; + +static void __attribute__ ((constructor)) basic_init(void) +{ + register_cls_module(&basic_module); +} + +static void __attribute__ ((destructor)) basic_exit(void) +{ + unregister_cls_module(&basic_module); +} diff --git a/src/cls/cgroup.c b/src/cls/cgroup.c new file mode 100644 index 0000000..ad0392f --- /dev/null +++ b/src/cls/cgroup.c @@ -0,0 +1,78 @@ +/* + * src/cls/cgroup.c Control Groups Classifier + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2 of the License. + * + * Copyright (c) 2009 Thomas Graf <tgraf@suug.ch> + */ + +#include "utils.h" +#include <netlink/route/cls/cgroup.h> +#include <netlink/route/cls/ematch.h> + +static void print_usage(void) +{ + printf( +"Usage: ... cgroup [OPTIONS]...\n" +"\n" +"Options\n" +" -h, --help Show this help.\n" +" -e, --ematch=MATCH Extended match (See --ematch help).\n" +" -c, --classid=HANDLE Target class to classify matching packets to.\n" + ); + exit(0); +} + +static void basic_parse_argv(struct rtnl_cls *cls, int argc, char **argv) +{ + for (;;) { + int c, optidx = 0; + static struct option long_opts[] = { + { "help", 0, 0, 'h' }, + { "ematch", 1, 0, 'e' }, + { "classid", 1, 0, 'c' }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "he:c:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case '?': + exit(NLE_INVAL); + + case 'h': + print_usage(); + +#if 0 + case 'e': + if ((err = parse_ematch_syntax(optarg, &tree)) < 0) + fatal(err, "Error while parsing ematch: %s", + nl_geterror(err)); + + if ((err = rtnl_basic_set_ematch(cls, tree)) < 0) + fatal(err, "Unable to set ematch: %s", + nl_geterror(err)); + break; +#endif + } + } +} + +static struct cls_module cgroup_module = { + .name = "cgroup", + .parse_argv = basic_parse_argv, +}; + +static void __init cgroup_init(void) +{ + register_cls_module(&cgroup_module); +} + +static void __exit cgroup_exit(void) +{ + unregister_cls_module(&cgroup_module); +} diff --git a/src/cls/utils.c b/src/cls/utils.c new file mode 100644 index 0000000..ef6603b --- /dev/null +++ b/src/cls/utils.c @@ -0,0 +1,105 @@ +/* + * src/cls-utils.c Classifier Helpers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2 of the License. + * + * Copyright (c) 2008-2009 Thomas Graf <tgraf@suug.ch> + */ + +#include "utils.h" + +struct rtnl_cls *nlt_alloc_cls(void) +{ + struct rtnl_cls *cls; + + cls = rtnl_cls_alloc(); + if (!cls) + fatal(ENOMEM, "Unable to allocate classifier object"); + + return cls; +} + +void parse_dev(struct rtnl_cls *cls, struct nl_cache *link_cache, char *arg) +{ + int ival; + + if (!(ival = rtnl_link_name2i(link_cache, arg))) + fatal(ENOENT, "Link \"%s\" does not exist", arg); + + rtnl_cls_set_ifindex(cls, ival); +} + +void parse_prio(struct rtnl_cls *cls, char *arg) +{ + uint32_t prio = parse_u32(arg); + rtnl_cls_set_prio(cls, prio); +} + +void parse_parent(struct rtnl_cls *cls, char *arg) +{ + uint32_t parent; + int err; + + if ((err = rtnl_tc_str2handle(arg, &parent)) < 0) + fatal(err, "Unable to parse handle \"%s\": %s", + arg, nl_geterror(err)); + + rtnl_cls_set_parent(cls, parent); +} + +void parse_handle(struct rtnl_cls *cls, char *arg) +{ + uint32_t handle; + int err; + + if ((err = rtnl_tc_str2handle(arg, &handle)) < 0) + fatal(err, "Unable to parse handle \"%s\": %s", + arg, nl_geterror(err)); + + rtnl_cls_set_handle(cls, handle); +} + +void parse_proto(struct rtnl_cls *cls, char *arg) +{ + int proto = nl_str2ether_proto(arg); + if (proto < 0) + fatal(proto, "Unable to parse protocol \"%s\": %s", + arg, nl_geterror(proto)); + rtnl_cls_set_protocol(cls, proto); +} + +static NL_LIST_HEAD(cls_modules); + +struct cls_module *lookup_cls_mod(struct rtnl_cls_ops *ops) +{ + struct cls_module *mod; + + nl_list_for_each_entry(mod, &cls_modules, list) { + if (mod->ops == ops) + return mod; + } + + return NULL; +} + +void register_cls_module(struct cls_module *mod) +{ + struct rtnl_cls_ops *ops; + + if (!(ops = __rtnl_cls_lookup_ops(mod->name))) + fatal(ENOENT, "Could not locate classifier module \"%s\"", + mod->name); + + if (lookup_cls_mod(ops) != NULL) + fatal(EEXIST, "Duplicate classifier module registration."); + + mod->ops = ops; + nl_list_add_tail(&mod->list, &cls_modules); +} + +void unregister_cls_module(struct cls_module *mod) +{ + nl_list_del(&mod->list); +} diff --git a/src/cls/utils.h b/src/cls/utils.h new file mode 100644 index 0000000..1a8ee9b --- /dev/null +++ b/src/cls/utils.h @@ -0,0 +1,51 @@ +/* + * src/cls-utils.h Classifier Helpers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2 of the License. + * + * Copyright (c) 2008-2009 Thomas Graf <tgraf@suug.ch> + */ + +#ifndef __CLS_UTILS_H_ +#define __CLS_UTILS_H_ + +#include "../utils.h" +#include <netlink/route/classifier-modules.h> +#include <netlink/route/cls/ematch.h> + +struct cls_module +{ + const char * name; + struct rtnl_cls_ops * ops; + void (*parse_argv)(struct rtnl_cls *, int, char **); + struct nl_list_head list; +}; + +extern struct cls_module *lookup_cls_mod(struct rtnl_cls_ops *); +extern void register_cls_module(struct cls_module *); +extern void unregister_cls_module(struct cls_module *); + +struct ematch_module +{ + int kind; + struct rtnl_ematch_ops *ops; + void (*parse_argv)(struct rtnl_ematch *, int, char **); + struct nl_list_head list; +}; + +extern struct ematch_module *lookup_ematch_mod(struct rtnl_ematch_ops *); +extern void register_ematch_module(struct ematch_module *); +extern void unregister_ematch_module(struct ematch_module *); + +extern struct rtnl_cls *nlt_alloc_cls(void); +extern void parse_dev(struct rtnl_cls *, struct nl_cache *, char *); +extern void parse_prio(struct rtnl_cls *, char *); +extern void parse_parent(struct rtnl_cls *, char *); +extern void parse_handle(struct rtnl_cls *, char *); +extern void parse_proto(struct rtnl_cls *, char *); + +extern int parse_ematch_syntax(const char *, struct rtnl_ematch_tree **); + +#endif diff --git a/src/nl-cls-add.c b/src/nl-cls-add.c new file mode 100644 index 0000000..997f02f --- /dev/null +++ b/src/nl-cls-add.c @@ -0,0 +1,117 @@ +/* + * src/nl-cls-add.c Add classifier + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2 of the License. + * + * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch> + */ + +#include "cls/utils.h" + +static int quiet = 0; + +static void print_usage(void) +{ + printf( +"Usage: nl-cls-add [OPTION]... [CLASSIFIER] TYPE [TYPE OPTIONS]...\n" +"\n" +"Options\n" +" -q, --quiet Do not print informal notifications.\n" +" -h, --help Show this help.\n" +" -v, --version Show versioning information.\n" +"\n" +"Classifier Options\n" +" -d, --dev=DEV Device the classifier should be assigned to.\n" +" -p, --parent=HANDLE Parent QDisc\n" +" --proto=PROTO Protocol (default=IPv4)\n" +" --prio=NUM Priority (0..256)\n" +" --id=HANDLE Unique identifier\n" + ); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct nl_sock *sock; + struct rtnl_cls *cls; + struct nl_cache *link_cache; + struct rtnl_cls_ops *ops; + struct cls_module *mod; + struct nl_dump_params dp = { + .dp_type = NL_DUMP_DETAILS, + .dp_fd = stdout, + }; + char *kind; + int err, nlflags = NLM_F_CREATE; + + sock = nlt_alloc_socket(); + nlt_connect(sock, NETLINK_ROUTE); + link_cache = nlt_alloc_link_cache(sock); + cls = nlt_alloc_cls(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_PROTO = 257, + ARG_PRIO = 258, + ARG_ID, + }; + static struct option long_opts[] = { + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "dev", 1, 0, 'd' }, + { "parent", 1, 0, 'p' }, + { "proto", 1, 0, ARG_PROTO }, + { "prio", 1, 0, ARG_PRIO }, + { "id", 1, 0, ARG_ID }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "+qhva:d:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case '?': exit(NLE_INVAL); + case 'q': quiet = 1; break; + case 'h': print_usage(); break; + case 'v': nlt_print_version(); break; + case 'd': parse_dev(cls, link_cache, optarg); break; + case 'p': parse_parent(cls, optarg); break; + case ARG_PRIO: parse_prio(cls, optarg); break; + case ARG_ID: parse_handle(cls, optarg); break; + case ARG_PROTO: parse_proto(cls, optarg); break; + } + } + + if (optind >= argc) { + print_usage(); + fatal(EINVAL, "Missing classifier type"); + } + + kind = argv[optind++]; + if ((err = rtnl_cls_set_kind(cls, kind)) < 0) + fatal(ENOENT, "Unknown classifier type \"%s\".", kind); + + ops = rtnl_cls_get_ops(cls); + if (!(mod = lookup_cls_mod(ops))) + fatal(ENOTSUP, "Classifier type \"%s\" not supported.", kind); + + mod->parse_argv(cls, argc, argv); + + printf("Adding "); + nl_object_dump(OBJ_CAST(cls), &dp); + + if ((err = rtnl_cls_add(sock, cls, nlflags)) < 0) + fatal(err, "Unable to add classifier: %s", nl_geterror(err)); + + if (!quiet) { + printf("Added "); + nl_object_dump(OBJ_CAST(cls), &dp); + } + + return 0; +} diff --git a/src/nl-cls-delete.c b/src/nl-cls-delete.c new file mode 100644 index 0000000..cfdc170 --- /dev/null +++ b/src/nl-cls-delete.c @@ -0,0 +1,133 @@ +/* + * src/nl-cls-delete.c Delete Classifier + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2008 Thomas Graf <tgraf@suug.ch> + */ + +#include "cls/utils.h" + +static int interactive = 0, default_yes = 0, quiet = 0; +static int deleted = 0; +static struct nl_sock *sock; + +static void print_usage(void) +{ + printf( + "Usage: nl-cls-list [OPTION]... [CLASSIFIER]\n" + "\n" + "Options\n" + " -i, --interactive Run interactively\n" + " --yes Set default answer to yes\n" + " -q, --quiet Do not print informal notifications\n" + " -h, --help Show this help\n" + " -v, --version Show versioning information\n" + "\n" + "Classifier Options\n" + " -d, --dev=DEV Device the classifier should be assigned to.\n" + " -p, --parent=HANDLE Parent qdisc/class\n" + " --proto=PROTO Protocol\n" + " --prio=NUM Priority (0..256)\n" + " --id=HANDLE Unique identifier\n" + ); + exit(0); +} + +static void delete_cb(struct nl_object *obj, void *arg) +{ + struct rtnl_cls *cls = (struct rtnl_cls *) obj; + struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, + .dp_fd = stdout, + }; + int err; + + if (interactive && !nlt_confirm(obj, ¶ms, default_yes)) + return; + + if ((err = rtnl_cls_delete(sock, cls, 0)) < 0) + fatal(err, "Unable to delete classifier: %s", + nl_geterror(err)); + + if (!quiet) { + printf("Deleted "); + nl_object_dump(obj, ¶ms); + } + + deleted++; +} + +int main(int argc, char *argv[]) +{ + struct nl_cache *link_cache, *cls_cache; + struct rtnl_cls *cls; + int nf = 0, err; + + sock = nlt_alloc_socket(); + nlt_connect(sock, NETLINK_ROUTE); + link_cache = nlt_alloc_link_cache(sock); + cls = nlt_alloc_cls(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_PRIO = 257, + ARG_PROTO = 258, + ARG_ID, + ARG_YES, + }; + static struct option long_opts[] = { + { "interactive", 0, 0, 'i' }, + { "yes", 0, 0, ARG_YES }, + { "quiet", 0, 0, 'q' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "dev", 1, 0, 'd' }, + { "parent", 1, 0, 'p' }, + { "proto", 1, 0, ARG_PROTO }, + { "prio", 1, 0, ARG_PRIO }, + { "id", 1, 0, ARG_ID }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "iqhvd:p:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case 'i': interactive = 1; break; + case ARG_YES: default_yes = 1; break; + case 'q': quiet = 1; break; + case 'h': print_usage(); break; + case 'v': nlt_print_version(); break; + case 'd': nf++; parse_dev(cls, link_cache, optarg); break; + case 'p': nf++; parse_parent(cls, optarg); break; + case ARG_PRIO: nf++; parse_prio(cls, optarg); break; + case ARG_ID: nf++; parse_handle(cls, optarg); break; + case ARG_PROTO: nf++; parse_proto(cls, optarg); break; + } + } + + if (nf == 0 && !interactive && !default_yes) { + fprintf(stderr, "You attempted to delete all classifiers in " + "non-interactive mode, aborting.\n"); + exit(0); + } + + err = rtnl_cls_alloc_cache(sock, rtnl_cls_get_ifindex(cls), + rtnl_cls_get_parent(cls), &cls_cache); + if (err < 0) + fatal(err, "Unable to allocate classifier cache: %s", + nl_geterror(err)); + + nl_cache_foreach_filter(cls_cache, OBJ_CAST(cls), delete_cb, NULL); + + if (!quiet) + printf("Deleted %d classifiers\n", deleted); + + return 0; +} diff --git a/src/nl-cls-list.c b/src/nl-cls-list.c new file mode 100644 index 0000000..9121d52 --- /dev/null +++ b/src/nl-cls-list.c @@ -0,0 +1,113 @@ +/* + * src/nl-cls-list.c List classifiers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2008 Thomas Graf <tgraf@suug.ch> + */ + +#include "cls/utils.h" + +static struct nl_sock *sock; +static struct rtnl_cls *cls; +static struct nl_dump_params params = { + .dp_type = NL_DUMP_LINE, +}; + +static void print_usage(void) +{ + printf( + "Usage: nl-cls-list [OPTION]... [CLASSIFIER]\n" + "\n" + "Options\n" + " -f, --format=TYPE Output format { brief | details | stats }\n" + " -h, --help Show this help text.\n" + " -v, --version Show versioning information.\n" + "\n" + "Classifier Options\n" + " -d, --dev=DEV Device the classifier should be assigned to.\n" + " -p, --parent=HANDLE Parent qdisc/class\n" + " --proto=PROTO Protocol\n" + " --prio=NUM Priority\n" + " --id=NUM Identifier\n" + ); + exit(0); +} + +static void print_cls(struct nl_object *obj, void *arg) +{ + struct nl_cache *cls_cache; + int err, ifindex; + + if (obj) + ifindex = rtnl_link_get_ifindex((struct rtnl_link *) obj); + else + ifindex = rtnl_cls_get_ifindex(cls); + + err = rtnl_cls_alloc_cache(sock, ifindex, rtnl_cls_get_parent(cls), + &cls_cache); + if (err < 0) + fatal(err, "Unable to allocate classifier cache: %s", + nl_geterror(err)); + + nl_cache_dump_filter(cls_cache, ¶ms, OBJ_CAST(cls)); + nl_cache_free(cls_cache); +} + +int main(int argc, char *argv[]) +{ + struct nl_cache *link_cache; + int dev = 0; + + params.dp_fd = stdout; + sock = nlt_alloc_socket(); + nlt_connect(sock, NETLINK_ROUTE); + link_cache = nlt_alloc_link_cache(sock); + cls = nlt_alloc_cls(); + + for (;;) { + int c, optidx = 0; + enum { + ARG_PROTO = 257, + ARG_PRIO = 258, + ARG_ID, + }; + static struct option long_opts[] = { + { "format", 1, 0, 'f' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'v' }, + { "dev", 1, 0, 'd' }, + { "parent", 1, 0, 'p' }, + { "proto", 1, 0, ARG_PROTO }, + { "prio", 1, 0, ARG_PRIO }, + { "id", 1, 0, ARG_ID }, + { 0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "+f:qhva:d:", long_opts, &optidx); + if (c == -1) + break; + + switch (c) { + case '?': exit(NLE_INVAL); + case 'f': params.dp_type = nlt_parse_dumptype(optarg); break; + case 'h': print_usage(); break; + case 'v': nlt_print_version(); break; + case 'd': dev = 1; parse_dev(cls, link_cache, optarg); break; + case 'p': parse_parent(cls, optarg); break; + case ARG_PRIO: parse_prio(cls, optarg); break; + case ARG_ID: parse_handle(cls, optarg); break; + case ARG_PROTO: parse_proto(cls, optarg); break; + } + } + + if (!dev) + nl_cache_foreach(link_cache, print_cls, NULL); + else + print_cls(NULL, NULL); + + return 0; +} diff --git a/src/nl-list-caches.c b/src/nl-list-caches.c index e9e81c5..abd5ff3 100644 --- a/src/nl-list-caches.c +++ b/src/nl-list-caches.c @@ -9,8 +9,8 @@ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch> */ -#include "utils.h" #include <netlink-local.h> +#include "utils.h" static void print_usage(void) { diff --git a/src/utils.h b/src/utils.h index a5c94e6..69b6fdc 100644 --- a/src/utils.h +++ b/src/utils.h @@ -36,6 +36,7 @@ #include <netlink/route/qdisc.h> #include <netlink/route/class.h> #include <netlink/route/classifier.h> +#include <netlink/route/cls/ematch.h> #include <netlink/fib_lookup/lookup.h> #include <netlink/fib_lookup/request.h> #include <netlink/genl/genl.h> @@ -43,6 +44,14 @@ #include <netlink/genl/mngt.h> #include <netlink/netfilter/ct.h> +#ifndef __init +#define __init __attribute__((constructor)) +#endif + +#ifndef __exit +#define __exit __attribute__((destructor)) +#endif + extern uint32_t parse_u32(const char *); extern void nlt_print_version(void); |