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 
13 static int quiet = 0;
14 
print_usage(void)15 static 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 
main(int argc,char * argv[])35 int 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