1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66#include <stdio.h>
67#include <stdlib.h>
68#include <unistd.h>
69#include <fcntl.h>
70#include <sys/socket.h>
71#include <netinet/in.h>
72#include <arpa/inet.h>
73#include <string.h>
74#include "utils.h"
75#include "tc_util.h"
76#include <linux/tc_act/tc_defact.h>
77
78#ifndef SIMP_MAX_DATA
79#define SIMP_MAX_DATA 32
80#endif
81static void explain(void)
82{
83 fprintf(stderr,
84 "Usage:... simple [sdata STRING] [index INDEX] [CONTROL]\n"
85 "\tSTRING being an arbitrary string\n"
86 "\tINDEX := optional index value used\n"
87 "\tCONTROL := reclassify|pipe|drop|continue|ok\n");
88}
89
90static void usage(void)
91{
92 explain();
93 exit(-1);
94}
95
96static int
97parse_simple(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
98 struct nlmsghdr *n)
99{
100 struct tc_defact sel = {};
101 int argc = *argc_p;
102 char **argv = *argv_p;
103 int ok = 0;
104 struct rtattr *tail;
105 char *simpdata = NULL;
106
107 while (argc > 0) {
108 if (matches(*argv, "simple") == 0) {
109 NEXT_ARG();
110 } else if (matches(*argv, "sdata") == 0) {
111 NEXT_ARG();
112 ok += 1;
113 simpdata = *argv;
114 argc--;
115 argv++;
116 } else if (matches(*argv, "help") == 0) {
117 usage();
118 } else {
119 break;
120 }
121 }
122
123 parse_action_control_dflt(&argc, &argv, &sel.action, false,
124 TC_ACT_PIPE);
125
126 if (argc) {
127 if (matches(*argv, "index") == 0) {
128 NEXT_ARG();
129 if (get_u32(&sel.index, *argv, 10)) {
130 fprintf(stderr, "simple: Illegal \"index\" (%s)\n",
131 *argv);
132 return -1;
133 }
134 ok += 1;
135 argc--;
136 argv++;
137 }
138 }
139
140 if (!ok) {
141 explain();
142 return -1;
143 }
144
145 if (simpdata && (strlen(simpdata) > (SIMP_MAX_DATA - 1))) {
146 fprintf(stderr, "simple: Illegal string len %zu <%s>\n",
147 strlen(simpdata), simpdata);
148 return -1;
149 }
150
151 tail = addattr_nest(n, MAX_MSG, tca_id);
152 addattr_l(n, MAX_MSG, TCA_DEF_PARMS, &sel, sizeof(sel));
153 if (simpdata)
154 addattr_l(n, MAX_MSG, TCA_DEF_DATA, simpdata, SIMP_MAX_DATA);
155 addattr_nest_end(n, tail);
156
157 *argc_p = argc;
158 *argv_p = argv;
159 return 0;
160}
161
162static int print_simple(struct action_util *au, FILE *f, struct rtattr *arg)
163{
164 struct tc_defact *sel;
165 struct rtattr *tb[TCA_DEF_MAX + 1];
166 char *simpdata;
167
168 if (arg == NULL)
169 return 0;
170
171 parse_rtattr_nested(tb, TCA_DEF_MAX, arg);
172
173 if (tb[TCA_DEF_PARMS] == NULL) {
174 fprintf(stderr, "Missing simple parameters\n");
175 return -1;
176 }
177 sel = RTA_DATA(tb[TCA_DEF_PARMS]);
178
179 if (tb[TCA_DEF_DATA] == NULL) {
180 fprintf(stderr, "Missing simple string\n");
181 return -1;
182 }
183
184 simpdata = RTA_DATA(tb[TCA_DEF_DATA]);
185
186 fprintf(f, "Simple <%s>\n", simpdata);
187 fprintf(f, "\t index %u ref %d bind %d", sel->index,
188 sel->refcnt, sel->bindcnt);
189
190 if (show_stats) {
191 if (tb[TCA_DEF_TM]) {
192 struct tcf_t *tm = RTA_DATA(tb[TCA_DEF_TM]);
193
194 print_tm(f, tm);
195 }
196 }
197 print_nl();
198
199 return 0;
200}
201
202struct action_util simple_action_util = {
203 .id = "simple",
204 .parse_aopt = parse_simple,
205 .print_aopt = print_simple,
206};
207