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