summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThomas Graf <tgr@lsx.localdomain>2009-09-02 18:31:14 +0200
committerThomas Graf <tgr@lsx.localdomain>2009-09-02 18:31:14 +0200
commitef858fb492dfe98e3ae194264fbc73649cf8493a (patch)
tree86e6c7adc5f4ba2294cb31a386c3f8d90c8b88be /src
parent7d249fc2e1d0cb06cd4a4dfcc0a3c425ce63def7 (diff)
downloadandroid_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/Makefile4
-rw-r--r--src/cls/basic.c90
-rw-r--r--src/cls/cgroup.c78
-rw-r--r--src/cls/utils.c105
-rw-r--r--src/cls/utils.h51
-rw-r--r--src/nl-cls-add.c117
-rw-r--r--src/nl-cls-delete.c133
-rw-r--r--src/nl-cls-list.c113
-rw-r--r--src/nl-list-caches.c2
-rw-r--r--src/utils.h9
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, &params, 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, &params);
+ }
+
+ 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, &params, 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);