1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch/*
2c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * src/nl-cls-add.c     Add classifier
3c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch *
4c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch *	This library is free software; you can redistribute it and/or
5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch *	modify it under the terms of the GNU General Public License as
6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch *	published by the Free Software Foundation version 2 of the License.
7c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch *
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch */
10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
11c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "cls/utils.h"
12c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic int quiet = 0;
14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic void print_usage(void)
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch{
17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	printf(
18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch"Usage: nl-cls-add [OPTION]... [CLASSIFIER] TYPE [TYPE OPTIONS]...\n"
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch"\n"
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch"Options\n"
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch" -q, --quiet               Do not print informal notifications.\n"
22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch" -h, --help                Show this help.\n"
23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch" -v, --version             Show versioning information.\n"
24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch"\n"
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch"Classifier Options\n"
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch" -d, --dev=DEV             Device the classifier should be assigned to.\n"
27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch" -p, --parent=HANDLE       Parent QDisc\n"
28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch"     --proto=PROTO         Protocol (default=IPv4)\n"
29c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch"     --prio=NUM            Priority (0..256)\n"
30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch"     --id=HANDLE           Unique identifier\n"
31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	);
32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	exit(0);
33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int main(int argc, char *argv[])
36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch{
37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	struct nl_sock *sock;
38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	struct rtnl_cls *cls;
39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	struct nl_cache *link_cache;
40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	struct rtnl_cls_ops *ops;
41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	struct cls_module *mod;
42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	struct nl_dump_params dp = {
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		.dp_type = NL_DUMP_DETAILS,
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		.dp_fd = stdout,
45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	};
46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	char *kind;
47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	int err, nlflags = NLM_F_CREATE;
48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	sock = nlt_alloc_socket();
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	nlt_connect(sock, NETLINK_ROUTE);
51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	link_cache = nlt_alloc_link_cache(sock);
52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	cls = nlt_alloc_cls();
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	for (;;) {
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		int c, optidx = 0;
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		enum {
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			ARG_PROTO = 257,
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			ARG_PRIO = 258,
59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			ARG_ID,
60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		};
61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		static struct option long_opts[] = {
62c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			{ "quiet", 0, 0, 'q' },
63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			{ "help", 0, 0, 'h' },
64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			{ "version", 0, 0, 'v' },
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			{ "dev", 1, 0, 'd' },
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			{ "parent", 1, 0, 'p' },
67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			{ "proto", 1, 0, ARG_PROTO },
68c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			{ "prio", 1, 0, ARG_PRIO },
69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			{ "id", 1, 0, ARG_ID },
70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch			{ 0, 0, 0, 0 }
71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		};
72c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
73c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		c = getopt_long(argc, argv, "+qhva:d:", long_opts, &optidx);
74c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		if (c == -1)
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch			break;
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		switch (c) {
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		case '?': exit(NLE_INVAL);
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)		case 'q': quiet = 1; break;
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)		case 'h': print_usage(); break;
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)		case 'v': nlt_print_version(); break;
82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		case 'd': parse_dev(cls, link_cache, optarg); break;
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)		case 'p': parse_parent(cls, optarg); break;
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)		case ARG_PRIO: parse_prio(cls, optarg); break;
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)		case ARG_ID: parse_handle(cls, optarg); break;
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)		case ARG_PROTO: parse_proto(cls, optarg); break;
87c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		}
88c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 	}
89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)	if (optind >= argc) {
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)		print_usage();
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)		fatal(EINVAL, "Missing classifier type");
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)	}
94c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	kind = argv[optind++];
96c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	if ((err = rtnl_cls_set_kind(cls, kind)) < 0)
97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		fatal(ENOENT, "Unknown classifier type \"%s\".", kind);
98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	ops = rtnl_cls_get_ops(cls);
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	if (!(mod = lookup_cls_mod(ops)))
101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		fatal(ENOTSUP, "Classifier type \"%s\" not supported.", kind);
102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	mod->parse_argv(cls, argc, argv);
104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	printf("Adding ");
106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	nl_object_dump(OBJ_CAST(cls), &dp);
107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	if ((err = rtnl_cls_add(sock, cls, nlflags)) < 0)
109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		fatal(err, "Unable to add classifier: %s", nl_geterror(err));
110c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	if (!quiet) {
112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		printf("Added ");
113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch		nl_object_dump(OBJ_CAST(cls), &dp);
114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 	}
115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	return 0;
117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
118c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch