1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * q_u32.c U32 filter.
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can u32istribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker * 2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker *
9*de1e4e89SAndroid Build Coastguard Worker * Authors: Alexey Kuznetsov, <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker * Match mark added by Catalin(ux aka Dino) BOIE <catab at umbrella.ro> [5 nov 2004]
11*de1e4e89SAndroid Build Coastguard Worker *
12*de1e4e89SAndroid Build Coastguard Worker */
13*de1e4e89SAndroid Build Coastguard Worker
14*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <syslog.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
22*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
23*de1e4e89SAndroid Build Coastguard Worker #include <linux/if.h>
24*de1e4e89SAndroid Build Coastguard Worker #include <linux/if_ether.h>
25*de1e4e89SAndroid Build Coastguard Worker
26*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
27*de1e4e89SAndroid Build Coastguard Worker #include "tc_util.h"
28*de1e4e89SAndroid Build Coastguard Worker
29*de1e4e89SAndroid Build Coastguard Worker extern int show_pretty;
30*de1e4e89SAndroid Build Coastguard Worker
explain(void)31*de1e4e89SAndroid Build Coastguard Worker static void explain(void)
32*de1e4e89SAndroid Build Coastguard Worker {
33*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
34*de1e4e89SAndroid Build Coastguard Worker "Usage: ... u32 [ match SELECTOR ... ] [ link HTID ] [ classid CLASSID ]\n"
35*de1e4e89SAndroid Build Coastguard Worker " [ action ACTION_SPEC ] [ offset OFFSET_SPEC ]\n"
36*de1e4e89SAndroid Build Coastguard Worker " [ ht HTID ] [ hashkey HASHKEY_SPEC ]\n"
37*de1e4e89SAndroid Build Coastguard Worker " [ sample SAMPLE ] [skip_hw | skip_sw]\n"
38*de1e4e89SAndroid Build Coastguard Worker "or u32 divisor DIVISOR\n"
39*de1e4e89SAndroid Build Coastguard Worker "\n"
40*de1e4e89SAndroid Build Coastguard Worker "Where: SELECTOR := SAMPLE SAMPLE ...\n"
41*de1e4e89SAndroid Build Coastguard Worker " SAMPLE := { ip | ip6 | udp | tcp | icmp | u{32|16|8} | mark }\n"
42*de1e4e89SAndroid Build Coastguard Worker " SAMPLE_ARGS [ divisor DIVISOR ]\n"
43*de1e4e89SAndroid Build Coastguard Worker " FILTERID := X:Y:Z\n"
44*de1e4e89SAndroid Build Coastguard Worker "\nNOTE: CLASSID is parsed at hexadecimal input.\n");
45*de1e4e89SAndroid Build Coastguard Worker }
46*de1e4e89SAndroid Build Coastguard Worker
get_u32_handle(__u32 * handle,const char * str)47*de1e4e89SAndroid Build Coastguard Worker static int get_u32_handle(__u32 *handle, const char *str)
48*de1e4e89SAndroid Build Coastguard Worker {
49*de1e4e89SAndroid Build Coastguard Worker __u32 htid = 0, hash = 0, nodeid = 0;
50*de1e4e89SAndroid Build Coastguard Worker char *tmp = strchr(str, ':');
51*de1e4e89SAndroid Build Coastguard Worker
52*de1e4e89SAndroid Build Coastguard Worker if (tmp == NULL) {
53*de1e4e89SAndroid Build Coastguard Worker if (memcmp("0x", str, 2) == 0)
54*de1e4e89SAndroid Build Coastguard Worker return get_u32(handle, str, 16);
55*de1e4e89SAndroid Build Coastguard Worker return -1;
56*de1e4e89SAndroid Build Coastguard Worker }
57*de1e4e89SAndroid Build Coastguard Worker htid = strtoul(str, &tmp, 16);
58*de1e4e89SAndroid Build Coastguard Worker if (tmp == str && *str != ':' && *str != 0)
59*de1e4e89SAndroid Build Coastguard Worker return -1;
60*de1e4e89SAndroid Build Coastguard Worker if (htid >= 0x1000)
61*de1e4e89SAndroid Build Coastguard Worker return -1;
62*de1e4e89SAndroid Build Coastguard Worker if (*tmp) {
63*de1e4e89SAndroid Build Coastguard Worker str = tmp + 1;
64*de1e4e89SAndroid Build Coastguard Worker hash = strtoul(str, &tmp, 16);
65*de1e4e89SAndroid Build Coastguard Worker if (tmp == str && *str != ':' && *str != 0)
66*de1e4e89SAndroid Build Coastguard Worker return -1;
67*de1e4e89SAndroid Build Coastguard Worker if (hash >= 0x100)
68*de1e4e89SAndroid Build Coastguard Worker return -1;
69*de1e4e89SAndroid Build Coastguard Worker if (*tmp) {
70*de1e4e89SAndroid Build Coastguard Worker str = tmp + 1;
71*de1e4e89SAndroid Build Coastguard Worker nodeid = strtoul(str, &tmp, 16);
72*de1e4e89SAndroid Build Coastguard Worker if (tmp == str && *str != 0)
73*de1e4e89SAndroid Build Coastguard Worker return -1;
74*de1e4e89SAndroid Build Coastguard Worker if (nodeid >= 0x1000)
75*de1e4e89SAndroid Build Coastguard Worker return -1;
76*de1e4e89SAndroid Build Coastguard Worker }
77*de1e4e89SAndroid Build Coastguard Worker }
78*de1e4e89SAndroid Build Coastguard Worker *handle = (htid<<20)|(hash<<12)|nodeid;
79*de1e4e89SAndroid Build Coastguard Worker return 0;
80*de1e4e89SAndroid Build Coastguard Worker }
81*de1e4e89SAndroid Build Coastguard Worker
sprint_u32_handle(__u32 handle,char * buf)82*de1e4e89SAndroid Build Coastguard Worker static char *sprint_u32_handle(__u32 handle, char *buf)
83*de1e4e89SAndroid Build Coastguard Worker {
84*de1e4e89SAndroid Build Coastguard Worker int bsize = SPRINT_BSIZE-1;
85*de1e4e89SAndroid Build Coastguard Worker __u32 htid = TC_U32_HTID(handle);
86*de1e4e89SAndroid Build Coastguard Worker __u32 hash = TC_U32_HASH(handle);
87*de1e4e89SAndroid Build Coastguard Worker __u32 nodeid = TC_U32_NODE(handle);
88*de1e4e89SAndroid Build Coastguard Worker char *b = buf;
89*de1e4e89SAndroid Build Coastguard Worker
90*de1e4e89SAndroid Build Coastguard Worker if (handle == 0) {
91*de1e4e89SAndroid Build Coastguard Worker snprintf(b, bsize, "none");
92*de1e4e89SAndroid Build Coastguard Worker return b;
93*de1e4e89SAndroid Build Coastguard Worker }
94*de1e4e89SAndroid Build Coastguard Worker if (htid) {
95*de1e4e89SAndroid Build Coastguard Worker int l = snprintf(b, bsize, "%x:", htid>>20);
96*de1e4e89SAndroid Build Coastguard Worker
97*de1e4e89SAndroid Build Coastguard Worker bsize -= l;
98*de1e4e89SAndroid Build Coastguard Worker b += l;
99*de1e4e89SAndroid Build Coastguard Worker }
100*de1e4e89SAndroid Build Coastguard Worker if (nodeid|hash) {
101*de1e4e89SAndroid Build Coastguard Worker if (hash) {
102*de1e4e89SAndroid Build Coastguard Worker int l = snprintf(b, bsize, "%x", hash);
103*de1e4e89SAndroid Build Coastguard Worker
104*de1e4e89SAndroid Build Coastguard Worker bsize -= l;
105*de1e4e89SAndroid Build Coastguard Worker b += l;
106*de1e4e89SAndroid Build Coastguard Worker }
107*de1e4e89SAndroid Build Coastguard Worker if (nodeid) {
108*de1e4e89SAndroid Build Coastguard Worker int l = snprintf(b, bsize, ":%x", nodeid);
109*de1e4e89SAndroid Build Coastguard Worker
110*de1e4e89SAndroid Build Coastguard Worker bsize -= l;
111*de1e4e89SAndroid Build Coastguard Worker b += l;
112*de1e4e89SAndroid Build Coastguard Worker }
113*de1e4e89SAndroid Build Coastguard Worker }
114*de1e4e89SAndroid Build Coastguard Worker if (show_raw)
115*de1e4e89SAndroid Build Coastguard Worker snprintf(b, bsize, "[%08x] ", handle);
116*de1e4e89SAndroid Build Coastguard Worker return buf;
117*de1e4e89SAndroid Build Coastguard Worker }
118*de1e4e89SAndroid Build Coastguard Worker
pack_key(struct tc_u32_sel * sel,__u32 key,__u32 mask,int off,int offmask)119*de1e4e89SAndroid Build Coastguard Worker static int pack_key(struct tc_u32_sel *sel, __u32 key, __u32 mask,
120*de1e4e89SAndroid Build Coastguard Worker int off, int offmask)
121*de1e4e89SAndroid Build Coastguard Worker {
122*de1e4e89SAndroid Build Coastguard Worker int i;
123*de1e4e89SAndroid Build Coastguard Worker int hwm = sel->nkeys;
124*de1e4e89SAndroid Build Coastguard Worker
125*de1e4e89SAndroid Build Coastguard Worker key &= mask;
126*de1e4e89SAndroid Build Coastguard Worker
127*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < hwm; i++) {
128*de1e4e89SAndroid Build Coastguard Worker if (sel->keys[i].off == off && sel->keys[i].offmask == offmask) {
129*de1e4e89SAndroid Build Coastguard Worker __u32 intersect = mask & sel->keys[i].mask;
130*de1e4e89SAndroid Build Coastguard Worker
131*de1e4e89SAndroid Build Coastguard Worker if ((key ^ sel->keys[i].val) & intersect)
132*de1e4e89SAndroid Build Coastguard Worker return -1;
133*de1e4e89SAndroid Build Coastguard Worker sel->keys[i].val |= key;
134*de1e4e89SAndroid Build Coastguard Worker sel->keys[i].mask |= mask;
135*de1e4e89SAndroid Build Coastguard Worker return 0;
136*de1e4e89SAndroid Build Coastguard Worker }
137*de1e4e89SAndroid Build Coastguard Worker }
138*de1e4e89SAndroid Build Coastguard Worker
139*de1e4e89SAndroid Build Coastguard Worker if (hwm >= 128)
140*de1e4e89SAndroid Build Coastguard Worker return -1;
141*de1e4e89SAndroid Build Coastguard Worker if (off % 4)
142*de1e4e89SAndroid Build Coastguard Worker return -1;
143*de1e4e89SAndroid Build Coastguard Worker sel->keys[hwm].val = key;
144*de1e4e89SAndroid Build Coastguard Worker sel->keys[hwm].mask = mask;
145*de1e4e89SAndroid Build Coastguard Worker sel->keys[hwm].off = off;
146*de1e4e89SAndroid Build Coastguard Worker sel->keys[hwm].offmask = offmask;
147*de1e4e89SAndroid Build Coastguard Worker sel->nkeys++;
148*de1e4e89SAndroid Build Coastguard Worker return 0;
149*de1e4e89SAndroid Build Coastguard Worker }
150*de1e4e89SAndroid Build Coastguard Worker
pack_key32(struct tc_u32_sel * sel,__u32 key,__u32 mask,int off,int offmask)151*de1e4e89SAndroid Build Coastguard Worker static int pack_key32(struct tc_u32_sel *sel, __u32 key, __u32 mask,
152*de1e4e89SAndroid Build Coastguard Worker int off, int offmask)
153*de1e4e89SAndroid Build Coastguard Worker {
154*de1e4e89SAndroid Build Coastguard Worker key = htonl(key);
155*de1e4e89SAndroid Build Coastguard Worker mask = htonl(mask);
156*de1e4e89SAndroid Build Coastguard Worker return pack_key(sel, key, mask, off, offmask);
157*de1e4e89SAndroid Build Coastguard Worker }
158*de1e4e89SAndroid Build Coastguard Worker
pack_key16(struct tc_u32_sel * sel,__u32 key,__u32 mask,int off,int offmask)159*de1e4e89SAndroid Build Coastguard Worker static int pack_key16(struct tc_u32_sel *sel, __u32 key, __u32 mask,
160*de1e4e89SAndroid Build Coastguard Worker int off, int offmask)
161*de1e4e89SAndroid Build Coastguard Worker {
162*de1e4e89SAndroid Build Coastguard Worker if (key > 0xFFFF || mask > 0xFFFF)
163*de1e4e89SAndroid Build Coastguard Worker return -1;
164*de1e4e89SAndroid Build Coastguard Worker
165*de1e4e89SAndroid Build Coastguard Worker if ((off & 3) == 0) {
166*de1e4e89SAndroid Build Coastguard Worker key <<= 16;
167*de1e4e89SAndroid Build Coastguard Worker mask <<= 16;
168*de1e4e89SAndroid Build Coastguard Worker }
169*de1e4e89SAndroid Build Coastguard Worker off &= ~3;
170*de1e4e89SAndroid Build Coastguard Worker key = htonl(key);
171*de1e4e89SAndroid Build Coastguard Worker mask = htonl(mask);
172*de1e4e89SAndroid Build Coastguard Worker
173*de1e4e89SAndroid Build Coastguard Worker return pack_key(sel, key, mask, off, offmask);
174*de1e4e89SAndroid Build Coastguard Worker }
175*de1e4e89SAndroid Build Coastguard Worker
pack_key8(struct tc_u32_sel * sel,__u32 key,__u32 mask,int off,int offmask)176*de1e4e89SAndroid Build Coastguard Worker static int pack_key8(struct tc_u32_sel *sel, __u32 key, __u32 mask, int off,
177*de1e4e89SAndroid Build Coastguard Worker int offmask)
178*de1e4e89SAndroid Build Coastguard Worker {
179*de1e4e89SAndroid Build Coastguard Worker if (key > 0xFF || mask > 0xFF)
180*de1e4e89SAndroid Build Coastguard Worker return -1;
181*de1e4e89SAndroid Build Coastguard Worker
182*de1e4e89SAndroid Build Coastguard Worker if ((off & 3) == 0) {
183*de1e4e89SAndroid Build Coastguard Worker key <<= 24;
184*de1e4e89SAndroid Build Coastguard Worker mask <<= 24;
185*de1e4e89SAndroid Build Coastguard Worker } else if ((off & 3) == 1) {
186*de1e4e89SAndroid Build Coastguard Worker key <<= 16;
187*de1e4e89SAndroid Build Coastguard Worker mask <<= 16;
188*de1e4e89SAndroid Build Coastguard Worker } else if ((off & 3) == 2) {
189*de1e4e89SAndroid Build Coastguard Worker key <<= 8;
190*de1e4e89SAndroid Build Coastguard Worker mask <<= 8;
191*de1e4e89SAndroid Build Coastguard Worker }
192*de1e4e89SAndroid Build Coastguard Worker off &= ~3;
193*de1e4e89SAndroid Build Coastguard Worker key = htonl(key);
194*de1e4e89SAndroid Build Coastguard Worker mask = htonl(mask);
195*de1e4e89SAndroid Build Coastguard Worker
196*de1e4e89SAndroid Build Coastguard Worker return pack_key(sel, key, mask, off, offmask);
197*de1e4e89SAndroid Build Coastguard Worker }
198*de1e4e89SAndroid Build Coastguard Worker
199*de1e4e89SAndroid Build Coastguard Worker
parse_at(int * argc_p,char *** argv_p,int * off,int * offmask)200*de1e4e89SAndroid Build Coastguard Worker static int parse_at(int *argc_p, char ***argv_p, int *off, int *offmask)
201*de1e4e89SAndroid Build Coastguard Worker {
202*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
203*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
204*de1e4e89SAndroid Build Coastguard Worker char *p = *argv;
205*de1e4e89SAndroid Build Coastguard Worker
206*de1e4e89SAndroid Build Coastguard Worker if (argc <= 0)
207*de1e4e89SAndroid Build Coastguard Worker return -1;
208*de1e4e89SAndroid Build Coastguard Worker
209*de1e4e89SAndroid Build Coastguard Worker if (strlen(p) > strlen("nexthdr+") &&
210*de1e4e89SAndroid Build Coastguard Worker memcmp(p, "nexthdr+", strlen("nexthdr+")) == 0) {
211*de1e4e89SAndroid Build Coastguard Worker *offmask = -1;
212*de1e4e89SAndroid Build Coastguard Worker p += strlen("nexthdr+");
213*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "nexthdr+") == 0) {
214*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
215*de1e4e89SAndroid Build Coastguard Worker *offmask = -1;
216*de1e4e89SAndroid Build Coastguard Worker p = *argv;
217*de1e4e89SAndroid Build Coastguard Worker }
218*de1e4e89SAndroid Build Coastguard Worker
219*de1e4e89SAndroid Build Coastguard Worker if (get_integer(off, p, 0))
220*de1e4e89SAndroid Build Coastguard Worker return -1;
221*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
222*de1e4e89SAndroid Build Coastguard Worker
223*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
224*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
225*de1e4e89SAndroid Build Coastguard Worker return 0;
226*de1e4e89SAndroid Build Coastguard Worker }
227*de1e4e89SAndroid Build Coastguard Worker
228*de1e4e89SAndroid Build Coastguard Worker
parse_u32(int * argc_p,char *** argv_p,struct tc_u32_sel * sel,int off,int offmask)229*de1e4e89SAndroid Build Coastguard Worker static int parse_u32(int *argc_p, char ***argv_p, struct tc_u32_sel *sel,
230*de1e4e89SAndroid Build Coastguard Worker int off, int offmask)
231*de1e4e89SAndroid Build Coastguard Worker {
232*de1e4e89SAndroid Build Coastguard Worker int res = -1;
233*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
234*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
235*de1e4e89SAndroid Build Coastguard Worker __u32 key;
236*de1e4e89SAndroid Build Coastguard Worker __u32 mask;
237*de1e4e89SAndroid Build Coastguard Worker
238*de1e4e89SAndroid Build Coastguard Worker if (argc < 2)
239*de1e4e89SAndroid Build Coastguard Worker return -1;
240*de1e4e89SAndroid Build Coastguard Worker
241*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&key, *argv, 0))
242*de1e4e89SAndroid Build Coastguard Worker return -1;
243*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
244*de1e4e89SAndroid Build Coastguard Worker
245*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&mask, *argv, 16))
246*de1e4e89SAndroid Build Coastguard Worker return -1;
247*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
248*de1e4e89SAndroid Build Coastguard Worker
249*de1e4e89SAndroid Build Coastguard Worker if (argc > 0 && strcmp(argv[0], "at") == 0) {
250*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
251*de1e4e89SAndroid Build Coastguard Worker if (parse_at(&argc, &argv, &off, &offmask))
252*de1e4e89SAndroid Build Coastguard Worker return -1;
253*de1e4e89SAndroid Build Coastguard Worker }
254*de1e4e89SAndroid Build Coastguard Worker
255*de1e4e89SAndroid Build Coastguard Worker res = pack_key32(sel, key, mask, off, offmask);
256*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
257*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
258*de1e4e89SAndroid Build Coastguard Worker return res;
259*de1e4e89SAndroid Build Coastguard Worker }
260*de1e4e89SAndroid Build Coastguard Worker
parse_u16(int * argc_p,char *** argv_p,struct tc_u32_sel * sel,int off,int offmask)261*de1e4e89SAndroid Build Coastguard Worker static int parse_u16(int *argc_p, char ***argv_p, struct tc_u32_sel *sel,
262*de1e4e89SAndroid Build Coastguard Worker int off, int offmask)
263*de1e4e89SAndroid Build Coastguard Worker {
264*de1e4e89SAndroid Build Coastguard Worker int res = -1;
265*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
266*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
267*de1e4e89SAndroid Build Coastguard Worker __u32 key;
268*de1e4e89SAndroid Build Coastguard Worker __u32 mask;
269*de1e4e89SAndroid Build Coastguard Worker
270*de1e4e89SAndroid Build Coastguard Worker if (argc < 2)
271*de1e4e89SAndroid Build Coastguard Worker return -1;
272*de1e4e89SAndroid Build Coastguard Worker
273*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&key, *argv, 0))
274*de1e4e89SAndroid Build Coastguard Worker return -1;
275*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
276*de1e4e89SAndroid Build Coastguard Worker
277*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&mask, *argv, 16))
278*de1e4e89SAndroid Build Coastguard Worker return -1;
279*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
280*de1e4e89SAndroid Build Coastguard Worker
281*de1e4e89SAndroid Build Coastguard Worker if (argc > 0 && strcmp(argv[0], "at") == 0) {
282*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
283*de1e4e89SAndroid Build Coastguard Worker if (parse_at(&argc, &argv, &off, &offmask))
284*de1e4e89SAndroid Build Coastguard Worker return -1;
285*de1e4e89SAndroid Build Coastguard Worker }
286*de1e4e89SAndroid Build Coastguard Worker res = pack_key16(sel, key, mask, off, offmask);
287*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
288*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
289*de1e4e89SAndroid Build Coastguard Worker return res;
290*de1e4e89SAndroid Build Coastguard Worker }
291*de1e4e89SAndroid Build Coastguard Worker
parse_u8(int * argc_p,char *** argv_p,struct tc_u32_sel * sel,int off,int offmask)292*de1e4e89SAndroid Build Coastguard Worker static int parse_u8(int *argc_p, char ***argv_p, struct tc_u32_sel *sel,
293*de1e4e89SAndroid Build Coastguard Worker int off, int offmask)
294*de1e4e89SAndroid Build Coastguard Worker {
295*de1e4e89SAndroid Build Coastguard Worker int res = -1;
296*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
297*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
298*de1e4e89SAndroid Build Coastguard Worker __u32 key;
299*de1e4e89SAndroid Build Coastguard Worker __u32 mask;
300*de1e4e89SAndroid Build Coastguard Worker
301*de1e4e89SAndroid Build Coastguard Worker if (argc < 2)
302*de1e4e89SAndroid Build Coastguard Worker return -1;
303*de1e4e89SAndroid Build Coastguard Worker
304*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&key, *argv, 0))
305*de1e4e89SAndroid Build Coastguard Worker return -1;
306*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
307*de1e4e89SAndroid Build Coastguard Worker
308*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&mask, *argv, 16))
309*de1e4e89SAndroid Build Coastguard Worker return -1;
310*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
311*de1e4e89SAndroid Build Coastguard Worker
312*de1e4e89SAndroid Build Coastguard Worker if (key > 0xFF || mask > 0xFF)
313*de1e4e89SAndroid Build Coastguard Worker return -1;
314*de1e4e89SAndroid Build Coastguard Worker
315*de1e4e89SAndroid Build Coastguard Worker if (argc > 0 && strcmp(argv[0], "at") == 0) {
316*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
317*de1e4e89SAndroid Build Coastguard Worker if (parse_at(&argc, &argv, &off, &offmask))
318*de1e4e89SAndroid Build Coastguard Worker return -1;
319*de1e4e89SAndroid Build Coastguard Worker }
320*de1e4e89SAndroid Build Coastguard Worker
321*de1e4e89SAndroid Build Coastguard Worker res = pack_key8(sel, key, mask, off, offmask);
322*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
323*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
324*de1e4e89SAndroid Build Coastguard Worker return res;
325*de1e4e89SAndroid Build Coastguard Worker }
326*de1e4e89SAndroid Build Coastguard Worker
parse_ip_addr(int * argc_p,char *** argv_p,struct tc_u32_sel * sel,int off)327*de1e4e89SAndroid Build Coastguard Worker static int parse_ip_addr(int *argc_p, char ***argv_p, struct tc_u32_sel *sel,
328*de1e4e89SAndroid Build Coastguard Worker int off)
329*de1e4e89SAndroid Build Coastguard Worker {
330*de1e4e89SAndroid Build Coastguard Worker int res = -1;
331*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
332*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
333*de1e4e89SAndroid Build Coastguard Worker inet_prefix addr;
334*de1e4e89SAndroid Build Coastguard Worker __u32 mask;
335*de1e4e89SAndroid Build Coastguard Worker int offmask = 0;
336*de1e4e89SAndroid Build Coastguard Worker
337*de1e4e89SAndroid Build Coastguard Worker if (argc < 1)
338*de1e4e89SAndroid Build Coastguard Worker return -1;
339*de1e4e89SAndroid Build Coastguard Worker
340*de1e4e89SAndroid Build Coastguard Worker if (get_prefix_1(&addr, *argv, AF_INET))
341*de1e4e89SAndroid Build Coastguard Worker return -1;
342*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
343*de1e4e89SAndroid Build Coastguard Worker
344*de1e4e89SAndroid Build Coastguard Worker if (argc > 0 && strcmp(argv[0], "at") == 0) {
345*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
346*de1e4e89SAndroid Build Coastguard Worker if (parse_at(&argc, &argv, &off, &offmask))
347*de1e4e89SAndroid Build Coastguard Worker return -1;
348*de1e4e89SAndroid Build Coastguard Worker }
349*de1e4e89SAndroid Build Coastguard Worker
350*de1e4e89SAndroid Build Coastguard Worker mask = 0;
351*de1e4e89SAndroid Build Coastguard Worker if (addr.bitlen)
352*de1e4e89SAndroid Build Coastguard Worker mask = htonl(0xFFFFFFFF << (32 - addr.bitlen));
353*de1e4e89SAndroid Build Coastguard Worker if (pack_key(sel, addr.data[0], mask, off, offmask) < 0)
354*de1e4e89SAndroid Build Coastguard Worker return -1;
355*de1e4e89SAndroid Build Coastguard Worker res = 0;
356*de1e4e89SAndroid Build Coastguard Worker
357*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
358*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
359*de1e4e89SAndroid Build Coastguard Worker return res;
360*de1e4e89SAndroid Build Coastguard Worker }
361*de1e4e89SAndroid Build Coastguard Worker
parse_ip6_addr(int * argc_p,char *** argv_p,struct tc_u32_sel * sel,int off)362*de1e4e89SAndroid Build Coastguard Worker static int parse_ip6_addr(int *argc_p, char ***argv_p,
363*de1e4e89SAndroid Build Coastguard Worker struct tc_u32_sel *sel, int off)
364*de1e4e89SAndroid Build Coastguard Worker {
365*de1e4e89SAndroid Build Coastguard Worker int res = -1;
366*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
367*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
368*de1e4e89SAndroid Build Coastguard Worker int plen = 128;
369*de1e4e89SAndroid Build Coastguard Worker int i;
370*de1e4e89SAndroid Build Coastguard Worker inet_prefix addr;
371*de1e4e89SAndroid Build Coastguard Worker int offmask = 0;
372*de1e4e89SAndroid Build Coastguard Worker
373*de1e4e89SAndroid Build Coastguard Worker if (argc < 1)
374*de1e4e89SAndroid Build Coastguard Worker return -1;
375*de1e4e89SAndroid Build Coastguard Worker
376*de1e4e89SAndroid Build Coastguard Worker if (get_prefix_1(&addr, *argv, AF_INET6))
377*de1e4e89SAndroid Build Coastguard Worker return -1;
378*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
379*de1e4e89SAndroid Build Coastguard Worker
380*de1e4e89SAndroid Build Coastguard Worker if (argc > 0 && strcmp(argv[0], "at") == 0) {
381*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
382*de1e4e89SAndroid Build Coastguard Worker if (parse_at(&argc, &argv, &off, &offmask))
383*de1e4e89SAndroid Build Coastguard Worker return -1;
384*de1e4e89SAndroid Build Coastguard Worker }
385*de1e4e89SAndroid Build Coastguard Worker
386*de1e4e89SAndroid Build Coastguard Worker plen = addr.bitlen;
387*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < plen; i += 32) {
388*de1e4e89SAndroid Build Coastguard Worker if (i + 31 < plen) {
389*de1e4e89SAndroid Build Coastguard Worker res = pack_key(sel, addr.data[i / 32],
390*de1e4e89SAndroid Build Coastguard Worker 0xFFFFFFFF, off + 4 * (i / 32), offmask);
391*de1e4e89SAndroid Build Coastguard Worker if (res < 0)
392*de1e4e89SAndroid Build Coastguard Worker return -1;
393*de1e4e89SAndroid Build Coastguard Worker } else if (i < plen) {
394*de1e4e89SAndroid Build Coastguard Worker __u32 mask = htonl(0xFFFFFFFF << (32 - (plen - i)));
395*de1e4e89SAndroid Build Coastguard Worker
396*de1e4e89SAndroid Build Coastguard Worker res = pack_key(sel, addr.data[i / 32],
397*de1e4e89SAndroid Build Coastguard Worker mask, off + 4 * (i / 32), offmask);
398*de1e4e89SAndroid Build Coastguard Worker if (res < 0)
399*de1e4e89SAndroid Build Coastguard Worker return -1;
400*de1e4e89SAndroid Build Coastguard Worker }
401*de1e4e89SAndroid Build Coastguard Worker }
402*de1e4e89SAndroid Build Coastguard Worker res = 0;
403*de1e4e89SAndroid Build Coastguard Worker
404*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
405*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
406*de1e4e89SAndroid Build Coastguard Worker return res;
407*de1e4e89SAndroid Build Coastguard Worker }
408*de1e4e89SAndroid Build Coastguard Worker
parse_ip6_class(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)409*de1e4e89SAndroid Build Coastguard Worker static int parse_ip6_class(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
410*de1e4e89SAndroid Build Coastguard Worker {
411*de1e4e89SAndroid Build Coastguard Worker int res = -1;
412*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
413*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
414*de1e4e89SAndroid Build Coastguard Worker __u32 key;
415*de1e4e89SAndroid Build Coastguard Worker __u32 mask;
416*de1e4e89SAndroid Build Coastguard Worker int off = 0;
417*de1e4e89SAndroid Build Coastguard Worker int offmask = 0;
418*de1e4e89SAndroid Build Coastguard Worker
419*de1e4e89SAndroid Build Coastguard Worker if (argc < 2)
420*de1e4e89SAndroid Build Coastguard Worker return -1;
421*de1e4e89SAndroid Build Coastguard Worker
422*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&key, *argv, 0))
423*de1e4e89SAndroid Build Coastguard Worker return -1;
424*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
425*de1e4e89SAndroid Build Coastguard Worker
426*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&mask, *argv, 16))
427*de1e4e89SAndroid Build Coastguard Worker return -1;
428*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
429*de1e4e89SAndroid Build Coastguard Worker
430*de1e4e89SAndroid Build Coastguard Worker if (key > 0xFF || mask > 0xFF)
431*de1e4e89SAndroid Build Coastguard Worker return -1;
432*de1e4e89SAndroid Build Coastguard Worker
433*de1e4e89SAndroid Build Coastguard Worker key <<= 20;
434*de1e4e89SAndroid Build Coastguard Worker mask <<= 20;
435*de1e4e89SAndroid Build Coastguard Worker key = htonl(key);
436*de1e4e89SAndroid Build Coastguard Worker mask = htonl(mask);
437*de1e4e89SAndroid Build Coastguard Worker
438*de1e4e89SAndroid Build Coastguard Worker res = pack_key(sel, key, mask, off, offmask);
439*de1e4e89SAndroid Build Coastguard Worker if (res < 0)
440*de1e4e89SAndroid Build Coastguard Worker return -1;
441*de1e4e89SAndroid Build Coastguard Worker
442*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
443*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
444*de1e4e89SAndroid Build Coastguard Worker return 0;
445*de1e4e89SAndroid Build Coastguard Worker }
446*de1e4e89SAndroid Build Coastguard Worker
parse_ether_addr(int * argc_p,char *** argv_p,struct tc_u32_sel * sel,int off)447*de1e4e89SAndroid Build Coastguard Worker static int parse_ether_addr(int *argc_p, char ***argv_p,
448*de1e4e89SAndroid Build Coastguard Worker struct tc_u32_sel *sel, int off)
449*de1e4e89SAndroid Build Coastguard Worker {
450*de1e4e89SAndroid Build Coastguard Worker int res = -1;
451*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
452*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
453*de1e4e89SAndroid Build Coastguard Worker __u8 addr[6];
454*de1e4e89SAndroid Build Coastguard Worker int offmask = 0;
455*de1e4e89SAndroid Build Coastguard Worker int i;
456*de1e4e89SAndroid Build Coastguard Worker
457*de1e4e89SAndroid Build Coastguard Worker if (argc < 1)
458*de1e4e89SAndroid Build Coastguard Worker return -1;
459*de1e4e89SAndroid Build Coastguard Worker
460*de1e4e89SAndroid Build Coastguard Worker if (sscanf(*argv, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
461*de1e4e89SAndroid Build Coastguard Worker addr + 0, addr + 1, addr + 2,
462*de1e4e89SAndroid Build Coastguard Worker addr + 3, addr + 4, addr + 5) != 6) {
463*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "parse_ether_addr: improperly formed address '%s'\n",
464*de1e4e89SAndroid Build Coastguard Worker *argv);
465*de1e4e89SAndroid Build Coastguard Worker return -1;
466*de1e4e89SAndroid Build Coastguard Worker }
467*de1e4e89SAndroid Build Coastguard Worker
468*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
469*de1e4e89SAndroid Build Coastguard Worker if (argc > 0 && strcmp(argv[0], "at") == 0) {
470*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
471*de1e4e89SAndroid Build Coastguard Worker if (parse_at(&argc, &argv, &off, &offmask))
472*de1e4e89SAndroid Build Coastguard Worker return -1;
473*de1e4e89SAndroid Build Coastguard Worker }
474*de1e4e89SAndroid Build Coastguard Worker
475*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < 6; i++) {
476*de1e4e89SAndroid Build Coastguard Worker res = pack_key8(sel, addr[i], 0xFF, off + i, offmask);
477*de1e4e89SAndroid Build Coastguard Worker if (res < 0)
478*de1e4e89SAndroid Build Coastguard Worker return -1;
479*de1e4e89SAndroid Build Coastguard Worker }
480*de1e4e89SAndroid Build Coastguard Worker
481*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
482*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
483*de1e4e89SAndroid Build Coastguard Worker return res;
484*de1e4e89SAndroid Build Coastguard Worker }
485*de1e4e89SAndroid Build Coastguard Worker
parse_ip(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)486*de1e4e89SAndroid Build Coastguard Worker static int parse_ip(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
487*de1e4e89SAndroid Build Coastguard Worker {
488*de1e4e89SAndroid Build Coastguard Worker int res = -1;
489*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
490*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
491*de1e4e89SAndroid Build Coastguard Worker
492*de1e4e89SAndroid Build Coastguard Worker if (argc < 2)
493*de1e4e89SAndroid Build Coastguard Worker return -1;
494*de1e4e89SAndroid Build Coastguard Worker
495*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "src") == 0) {
496*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
497*de1e4e89SAndroid Build Coastguard Worker res = parse_ip_addr(&argc, &argv, sel, 12);
498*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "dst") == 0) {
499*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
500*de1e4e89SAndroid Build Coastguard Worker res = parse_ip_addr(&argc, &argv, sel, 16);
501*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "tos") == 0 ||
502*de1e4e89SAndroid Build Coastguard Worker matches(*argv, "dsfield") == 0 ||
503*de1e4e89SAndroid Build Coastguard Worker matches(*argv, "precedence") == 0) {
504*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
505*de1e4e89SAndroid Build Coastguard Worker res = parse_u8(&argc, &argv, sel, 1, 0);
506*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "ihl") == 0) {
507*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
508*de1e4e89SAndroid Build Coastguard Worker res = parse_u8(&argc, &argv, sel, 0, 0);
509*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "protocol") == 0) {
510*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
511*de1e4e89SAndroid Build Coastguard Worker res = parse_u8(&argc, &argv, sel, 9, 0);
512*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "nofrag") == 0) {
513*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
514*de1e4e89SAndroid Build Coastguard Worker res = pack_key16(sel, 0, 0x3FFF, 6, 0);
515*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "firstfrag") == 0) {
516*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
517*de1e4e89SAndroid Build Coastguard Worker res = pack_key16(sel, 0x2000, 0x3FFF, 6, 0);
518*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "df") == 0) {
519*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
520*de1e4e89SAndroid Build Coastguard Worker res = pack_key16(sel, 0x4000, 0x4000, 6, 0);
521*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "mf") == 0) {
522*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
523*de1e4e89SAndroid Build Coastguard Worker res = pack_key16(sel, 0x2000, 0x2000, 6, 0);
524*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "dport") == 0) {
525*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
526*de1e4e89SAndroid Build Coastguard Worker res = parse_u16(&argc, &argv, sel, 22, 0);
527*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "sport") == 0) {
528*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
529*de1e4e89SAndroid Build Coastguard Worker res = parse_u16(&argc, &argv, sel, 20, 0);
530*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "icmp_type") == 0) {
531*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
532*de1e4e89SAndroid Build Coastguard Worker res = parse_u8(&argc, &argv, sel, 20, 0);
533*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "icmp_code") == 0) {
534*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
535*de1e4e89SAndroid Build Coastguard Worker res = parse_u8(&argc, &argv, sel, 21, 0);
536*de1e4e89SAndroid Build Coastguard Worker } else
537*de1e4e89SAndroid Build Coastguard Worker return -1;
538*de1e4e89SAndroid Build Coastguard Worker
539*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
540*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
541*de1e4e89SAndroid Build Coastguard Worker return res;
542*de1e4e89SAndroid Build Coastguard Worker }
543*de1e4e89SAndroid Build Coastguard Worker
parse_ip6(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)544*de1e4e89SAndroid Build Coastguard Worker static int parse_ip6(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
545*de1e4e89SAndroid Build Coastguard Worker {
546*de1e4e89SAndroid Build Coastguard Worker int res = -1;
547*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
548*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
549*de1e4e89SAndroid Build Coastguard Worker
550*de1e4e89SAndroid Build Coastguard Worker if (argc < 2)
551*de1e4e89SAndroid Build Coastguard Worker return -1;
552*de1e4e89SAndroid Build Coastguard Worker
553*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "src") == 0) {
554*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
555*de1e4e89SAndroid Build Coastguard Worker res = parse_ip6_addr(&argc, &argv, sel, 8);
556*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "dst") == 0) {
557*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
558*de1e4e89SAndroid Build Coastguard Worker res = parse_ip6_addr(&argc, &argv, sel, 24);
559*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "priority") == 0) {
560*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
561*de1e4e89SAndroid Build Coastguard Worker res = parse_ip6_class(&argc, &argv, sel);
562*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "protocol") == 0) {
563*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
564*de1e4e89SAndroid Build Coastguard Worker res = parse_u8(&argc, &argv, sel, 6, 0);
565*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "flowlabel") == 0) {
566*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
567*de1e4e89SAndroid Build Coastguard Worker res = parse_u32(&argc, &argv, sel, 0, 0);
568*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "dport") == 0) {
569*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
570*de1e4e89SAndroid Build Coastguard Worker res = parse_u16(&argc, &argv, sel, 42, 0);
571*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "sport") == 0) {
572*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
573*de1e4e89SAndroid Build Coastguard Worker res = parse_u16(&argc, &argv, sel, 40, 0);
574*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "icmp_type") == 0) {
575*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
576*de1e4e89SAndroid Build Coastguard Worker res = parse_u8(&argc, &argv, sel, 40, 0);
577*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "icmp_code") == 0) {
578*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
579*de1e4e89SAndroid Build Coastguard Worker res = parse_u8(&argc, &argv, sel, 41, 1);
580*de1e4e89SAndroid Build Coastguard Worker } else
581*de1e4e89SAndroid Build Coastguard Worker return -1;
582*de1e4e89SAndroid Build Coastguard Worker
583*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
584*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
585*de1e4e89SAndroid Build Coastguard Worker return res;
586*de1e4e89SAndroid Build Coastguard Worker }
587*de1e4e89SAndroid Build Coastguard Worker
parse_ether(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)588*de1e4e89SAndroid Build Coastguard Worker static int parse_ether(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
589*de1e4e89SAndroid Build Coastguard Worker {
590*de1e4e89SAndroid Build Coastguard Worker int res = -1;
591*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
592*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
593*de1e4e89SAndroid Build Coastguard Worker
594*de1e4e89SAndroid Build Coastguard Worker if (argc < 2)
595*de1e4e89SAndroid Build Coastguard Worker return -1;
596*de1e4e89SAndroid Build Coastguard Worker
597*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "src") == 0) {
598*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
599*de1e4e89SAndroid Build Coastguard Worker res = parse_ether_addr(&argc, &argv, sel, -8);
600*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "dst") == 0) {
601*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
602*de1e4e89SAndroid Build Coastguard Worker res = parse_ether_addr(&argc, &argv, sel, -14);
603*de1e4e89SAndroid Build Coastguard Worker } else {
604*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Unknown match: ether %s\n", *argv);
605*de1e4e89SAndroid Build Coastguard Worker return -1;
606*de1e4e89SAndroid Build Coastguard Worker }
607*de1e4e89SAndroid Build Coastguard Worker
608*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
609*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
610*de1e4e89SAndroid Build Coastguard Worker return res;
611*de1e4e89SAndroid Build Coastguard Worker }
612*de1e4e89SAndroid Build Coastguard Worker
613*de1e4e89SAndroid Build Coastguard Worker #define parse_tcp parse_udp
parse_udp(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)614*de1e4e89SAndroid Build Coastguard Worker static int parse_udp(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
615*de1e4e89SAndroid Build Coastguard Worker {
616*de1e4e89SAndroid Build Coastguard Worker int res = -1;
617*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
618*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
619*de1e4e89SAndroid Build Coastguard Worker
620*de1e4e89SAndroid Build Coastguard Worker if (argc < 2)
621*de1e4e89SAndroid Build Coastguard Worker return -1;
622*de1e4e89SAndroid Build Coastguard Worker
623*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "src") == 0) {
624*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
625*de1e4e89SAndroid Build Coastguard Worker res = parse_u16(&argc, &argv, sel, 0, -1);
626*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "dst") == 0) {
627*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
628*de1e4e89SAndroid Build Coastguard Worker res = parse_u16(&argc, &argv, sel, 2, -1);
629*de1e4e89SAndroid Build Coastguard Worker } else
630*de1e4e89SAndroid Build Coastguard Worker return -1;
631*de1e4e89SAndroid Build Coastguard Worker
632*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
633*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
634*de1e4e89SAndroid Build Coastguard Worker return res;
635*de1e4e89SAndroid Build Coastguard Worker }
636*de1e4e89SAndroid Build Coastguard Worker
637*de1e4e89SAndroid Build Coastguard Worker
parse_icmp(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)638*de1e4e89SAndroid Build Coastguard Worker static int parse_icmp(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
639*de1e4e89SAndroid Build Coastguard Worker {
640*de1e4e89SAndroid Build Coastguard Worker int res = -1;
641*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
642*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
643*de1e4e89SAndroid Build Coastguard Worker
644*de1e4e89SAndroid Build Coastguard Worker if (argc < 2)
645*de1e4e89SAndroid Build Coastguard Worker return -1;
646*de1e4e89SAndroid Build Coastguard Worker
647*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "type") == 0) {
648*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
649*de1e4e89SAndroid Build Coastguard Worker res = parse_u8(&argc, &argv, sel, 0, -1);
650*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "code") == 0) {
651*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
652*de1e4e89SAndroid Build Coastguard Worker res = parse_u8(&argc, &argv, sel, 1, -1);
653*de1e4e89SAndroid Build Coastguard Worker } else
654*de1e4e89SAndroid Build Coastguard Worker return -1;
655*de1e4e89SAndroid Build Coastguard Worker
656*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
657*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
658*de1e4e89SAndroid Build Coastguard Worker return res;
659*de1e4e89SAndroid Build Coastguard Worker }
660*de1e4e89SAndroid Build Coastguard Worker
parse_mark(int * argc_p,char *** argv_p,struct nlmsghdr * n)661*de1e4e89SAndroid Build Coastguard Worker static int parse_mark(int *argc_p, char ***argv_p, struct nlmsghdr *n)
662*de1e4e89SAndroid Build Coastguard Worker {
663*de1e4e89SAndroid Build Coastguard Worker int res = -1;
664*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
665*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
666*de1e4e89SAndroid Build Coastguard Worker struct tc_u32_mark mark;
667*de1e4e89SAndroid Build Coastguard Worker
668*de1e4e89SAndroid Build Coastguard Worker if (argc <= 1)
669*de1e4e89SAndroid Build Coastguard Worker return -1;
670*de1e4e89SAndroid Build Coastguard Worker
671*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&mark.val, *argv, 0)) {
672*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"mark\" value\n");
673*de1e4e89SAndroid Build Coastguard Worker return -1;
674*de1e4e89SAndroid Build Coastguard Worker }
675*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
676*de1e4e89SAndroid Build Coastguard Worker
677*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&mark.mask, *argv, 0)) {
678*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"mark\" mask\n");
679*de1e4e89SAndroid Build Coastguard Worker return -1;
680*de1e4e89SAndroid Build Coastguard Worker }
681*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
682*de1e4e89SAndroid Build Coastguard Worker
683*de1e4e89SAndroid Build Coastguard Worker if ((mark.val & mark.mask) != mark.val) {
684*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"mark\" (impossible combination)\n");
685*de1e4e89SAndroid Build Coastguard Worker return -1;
686*de1e4e89SAndroid Build Coastguard Worker }
687*de1e4e89SAndroid Build Coastguard Worker
688*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_U32_MARK, &mark, sizeof(mark));
689*de1e4e89SAndroid Build Coastguard Worker res = 0;
690*de1e4e89SAndroid Build Coastguard Worker
691*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
692*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
693*de1e4e89SAndroid Build Coastguard Worker return res;
694*de1e4e89SAndroid Build Coastguard Worker }
695*de1e4e89SAndroid Build Coastguard Worker
parse_selector(int * argc_p,char *** argv_p,struct tc_u32_sel * sel,struct nlmsghdr * n)696*de1e4e89SAndroid Build Coastguard Worker static int parse_selector(int *argc_p, char ***argv_p,
697*de1e4e89SAndroid Build Coastguard Worker struct tc_u32_sel *sel, struct nlmsghdr *n)
698*de1e4e89SAndroid Build Coastguard Worker {
699*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
700*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
701*de1e4e89SAndroid Build Coastguard Worker int res = -1;
702*de1e4e89SAndroid Build Coastguard Worker
703*de1e4e89SAndroid Build Coastguard Worker if (argc <= 0)
704*de1e4e89SAndroid Build Coastguard Worker return -1;
705*de1e4e89SAndroid Build Coastguard Worker
706*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "u32") == 0) {
707*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
708*de1e4e89SAndroid Build Coastguard Worker res = parse_u32(&argc, &argv, sel, 0, 0);
709*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "u16") == 0) {
710*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
711*de1e4e89SAndroid Build Coastguard Worker res = parse_u16(&argc, &argv, sel, 0, 0);
712*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "u8") == 0) {
713*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
714*de1e4e89SAndroid Build Coastguard Worker res = parse_u8(&argc, &argv, sel, 0, 0);
715*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "ip") == 0) {
716*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
717*de1e4e89SAndroid Build Coastguard Worker res = parse_ip(&argc, &argv, sel);
718*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "ip6") == 0) {
719*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
720*de1e4e89SAndroid Build Coastguard Worker res = parse_ip6(&argc, &argv, sel);
721*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "udp") == 0) {
722*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
723*de1e4e89SAndroid Build Coastguard Worker res = parse_udp(&argc, &argv, sel);
724*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "tcp") == 0) {
725*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
726*de1e4e89SAndroid Build Coastguard Worker res = parse_tcp(&argc, &argv, sel);
727*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "icmp") == 0) {
728*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
729*de1e4e89SAndroid Build Coastguard Worker res = parse_icmp(&argc, &argv, sel);
730*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "mark") == 0) {
731*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
732*de1e4e89SAndroid Build Coastguard Worker res = parse_mark(&argc, &argv, n);
733*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "ether") == 0) {
734*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
735*de1e4e89SAndroid Build Coastguard Worker res = parse_ether(&argc, &argv, sel);
736*de1e4e89SAndroid Build Coastguard Worker } else
737*de1e4e89SAndroid Build Coastguard Worker return -1;
738*de1e4e89SAndroid Build Coastguard Worker
739*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
740*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
741*de1e4e89SAndroid Build Coastguard Worker return res;
742*de1e4e89SAndroid Build Coastguard Worker }
743*de1e4e89SAndroid Build Coastguard Worker
parse_offset(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)744*de1e4e89SAndroid Build Coastguard Worker static int parse_offset(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
745*de1e4e89SAndroid Build Coastguard Worker {
746*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
747*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
748*de1e4e89SAndroid Build Coastguard Worker
749*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
750*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "plus") == 0) {
751*de1e4e89SAndroid Build Coastguard Worker int off;
752*de1e4e89SAndroid Build Coastguard Worker
753*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
754*de1e4e89SAndroid Build Coastguard Worker if (get_integer(&off, *argv, 0))
755*de1e4e89SAndroid Build Coastguard Worker return -1;
756*de1e4e89SAndroid Build Coastguard Worker sel->off = off;
757*de1e4e89SAndroid Build Coastguard Worker sel->flags |= TC_U32_OFFSET;
758*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "at") == 0) {
759*de1e4e89SAndroid Build Coastguard Worker int off;
760*de1e4e89SAndroid Build Coastguard Worker
761*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
762*de1e4e89SAndroid Build Coastguard Worker if (get_integer(&off, *argv, 0))
763*de1e4e89SAndroid Build Coastguard Worker return -1;
764*de1e4e89SAndroid Build Coastguard Worker sel->offoff = off;
765*de1e4e89SAndroid Build Coastguard Worker if (off%2) {
766*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "offset \"at\" must be even\n");
767*de1e4e89SAndroid Build Coastguard Worker return -1;
768*de1e4e89SAndroid Build Coastguard Worker }
769*de1e4e89SAndroid Build Coastguard Worker sel->flags |= TC_U32_VAROFFSET;
770*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "mask") == 0) {
771*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
772*de1e4e89SAndroid Build Coastguard Worker if (get_be16(&sel->offmask, *argv, 16))
773*de1e4e89SAndroid Build Coastguard Worker return -1;
774*de1e4e89SAndroid Build Coastguard Worker sel->flags |= TC_U32_VAROFFSET;
775*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "shift") == 0) {
776*de1e4e89SAndroid Build Coastguard Worker int shift;
777*de1e4e89SAndroid Build Coastguard Worker
778*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
779*de1e4e89SAndroid Build Coastguard Worker if (get_integer(&shift, *argv, 0))
780*de1e4e89SAndroid Build Coastguard Worker return -1;
781*de1e4e89SAndroid Build Coastguard Worker sel->offshift = shift;
782*de1e4e89SAndroid Build Coastguard Worker sel->flags |= TC_U32_VAROFFSET;
783*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "eat") == 0) {
784*de1e4e89SAndroid Build Coastguard Worker sel->flags |= TC_U32_EAT;
785*de1e4e89SAndroid Build Coastguard Worker } else {
786*de1e4e89SAndroid Build Coastguard Worker break;
787*de1e4e89SAndroid Build Coastguard Worker }
788*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
789*de1e4e89SAndroid Build Coastguard Worker }
790*de1e4e89SAndroid Build Coastguard Worker
791*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
792*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
793*de1e4e89SAndroid Build Coastguard Worker return 0;
794*de1e4e89SAndroid Build Coastguard Worker }
795*de1e4e89SAndroid Build Coastguard Worker
parse_hashkey(int * argc_p,char *** argv_p,struct tc_u32_sel * sel)796*de1e4e89SAndroid Build Coastguard Worker static int parse_hashkey(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
797*de1e4e89SAndroid Build Coastguard Worker {
798*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
799*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
800*de1e4e89SAndroid Build Coastguard Worker
801*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
802*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "mask") == 0) {
803*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
804*de1e4e89SAndroid Build Coastguard Worker if (get_be32(&sel->hmask, *argv, 16))
805*de1e4e89SAndroid Build Coastguard Worker return -1;
806*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "at") == 0) {
807*de1e4e89SAndroid Build Coastguard Worker int num;
808*de1e4e89SAndroid Build Coastguard Worker
809*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
810*de1e4e89SAndroid Build Coastguard Worker if (get_integer(&num, *argv, 0))
811*de1e4e89SAndroid Build Coastguard Worker return -1;
812*de1e4e89SAndroid Build Coastguard Worker if (num%4)
813*de1e4e89SAndroid Build Coastguard Worker return -1;
814*de1e4e89SAndroid Build Coastguard Worker sel->hoff = num;
815*de1e4e89SAndroid Build Coastguard Worker } else {
816*de1e4e89SAndroid Build Coastguard Worker break;
817*de1e4e89SAndroid Build Coastguard Worker }
818*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
819*de1e4e89SAndroid Build Coastguard Worker }
820*de1e4e89SAndroid Build Coastguard Worker
821*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
822*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
823*de1e4e89SAndroid Build Coastguard Worker return 0;
824*de1e4e89SAndroid Build Coastguard Worker }
825*de1e4e89SAndroid Build Coastguard Worker
print_ipv4(FILE * f,const struct tc_u32_key * key)826*de1e4e89SAndroid Build Coastguard Worker static void print_ipv4(FILE *f, const struct tc_u32_key *key)
827*de1e4e89SAndroid Build Coastguard Worker {
828*de1e4e89SAndroid Build Coastguard Worker char abuf[256];
829*de1e4e89SAndroid Build Coastguard Worker
830*de1e4e89SAndroid Build Coastguard Worker switch (key->off) {
831*de1e4e89SAndroid Build Coastguard Worker case 0:
832*de1e4e89SAndroid Build Coastguard Worker switch (ntohl(key->mask)) {
833*de1e4e89SAndroid Build Coastguard Worker case 0x0f000000:
834*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n match IP ihl %u",
835*de1e4e89SAndroid Build Coastguard Worker ntohl(key->val) >> 24);
836*de1e4e89SAndroid Build Coastguard Worker return;
837*de1e4e89SAndroid Build Coastguard Worker case 0x00ff0000:
838*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n match IP dsfield %#x",
839*de1e4e89SAndroid Build Coastguard Worker ntohl(key->val) >> 16);
840*de1e4e89SAndroid Build Coastguard Worker return;
841*de1e4e89SAndroid Build Coastguard Worker }
842*de1e4e89SAndroid Build Coastguard Worker break;
843*de1e4e89SAndroid Build Coastguard Worker case 8:
844*de1e4e89SAndroid Build Coastguard Worker if (ntohl(key->mask) == 0x00ff0000) {
845*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n match IP protocol %d",
846*de1e4e89SAndroid Build Coastguard Worker ntohl(key->val) >> 16);
847*de1e4e89SAndroid Build Coastguard Worker return;
848*de1e4e89SAndroid Build Coastguard Worker }
849*de1e4e89SAndroid Build Coastguard Worker break;
850*de1e4e89SAndroid Build Coastguard Worker case 12:
851*de1e4e89SAndroid Build Coastguard Worker case 16: {
852*de1e4e89SAndroid Build Coastguard Worker int bits = mask2bits(key->mask);
853*de1e4e89SAndroid Build Coastguard Worker
854*de1e4e89SAndroid Build Coastguard Worker if (bits >= 0) {
855*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n %s %s/%d",
856*de1e4e89SAndroid Build Coastguard Worker key->off == 12 ? "match IP src" : "match IP dst",
857*de1e4e89SAndroid Build Coastguard Worker inet_ntop(AF_INET, &key->val,
858*de1e4e89SAndroid Build Coastguard Worker abuf, sizeof(abuf)),
859*de1e4e89SAndroid Build Coastguard Worker bits);
860*de1e4e89SAndroid Build Coastguard Worker return;
861*de1e4e89SAndroid Build Coastguard Worker }
862*de1e4e89SAndroid Build Coastguard Worker }
863*de1e4e89SAndroid Build Coastguard Worker break;
864*de1e4e89SAndroid Build Coastguard Worker
865*de1e4e89SAndroid Build Coastguard Worker case 20:
866*de1e4e89SAndroid Build Coastguard Worker switch (ntohl(key->mask)) {
867*de1e4e89SAndroid Build Coastguard Worker case 0x0000ffff:
868*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n match dport %u",
869*de1e4e89SAndroid Build Coastguard Worker ntohl(key->val) & 0xffff);
870*de1e4e89SAndroid Build Coastguard Worker return;
871*de1e4e89SAndroid Build Coastguard Worker case 0xffff0000:
872*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n match sport %u",
873*de1e4e89SAndroid Build Coastguard Worker ntohl(key->val) >> 16);
874*de1e4e89SAndroid Build Coastguard Worker return;
875*de1e4e89SAndroid Build Coastguard Worker case 0xffffffff:
876*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n match dport %u, match sport %u",
877*de1e4e89SAndroid Build Coastguard Worker ntohl(key->val) & 0xffff,
878*de1e4e89SAndroid Build Coastguard Worker ntohl(key->val) >> 16);
879*de1e4e89SAndroid Build Coastguard Worker
880*de1e4e89SAndroid Build Coastguard Worker return;
881*de1e4e89SAndroid Build Coastguard Worker }
882*de1e4e89SAndroid Build Coastguard Worker /* XXX: Default print_raw */
883*de1e4e89SAndroid Build Coastguard Worker }
884*de1e4e89SAndroid Build Coastguard Worker }
885*de1e4e89SAndroid Build Coastguard Worker
print_ipv6(FILE * f,const struct tc_u32_key * key)886*de1e4e89SAndroid Build Coastguard Worker static void print_ipv6(FILE *f, const struct tc_u32_key *key)
887*de1e4e89SAndroid Build Coastguard Worker {
888*de1e4e89SAndroid Build Coastguard Worker char abuf[256];
889*de1e4e89SAndroid Build Coastguard Worker
890*de1e4e89SAndroid Build Coastguard Worker switch (key->off) {
891*de1e4e89SAndroid Build Coastguard Worker case 0:
892*de1e4e89SAndroid Build Coastguard Worker switch (ntohl(key->mask)) {
893*de1e4e89SAndroid Build Coastguard Worker case 0x0f000000:
894*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n match IP ihl %u",
895*de1e4e89SAndroid Build Coastguard Worker ntohl(key->val) >> 24);
896*de1e4e89SAndroid Build Coastguard Worker return;
897*de1e4e89SAndroid Build Coastguard Worker case 0x00ff0000:
898*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n match IP dsfield %#x",
899*de1e4e89SAndroid Build Coastguard Worker ntohl(key->val) >> 16);
900*de1e4e89SAndroid Build Coastguard Worker return;
901*de1e4e89SAndroid Build Coastguard Worker }
902*de1e4e89SAndroid Build Coastguard Worker break;
903*de1e4e89SAndroid Build Coastguard Worker case 8:
904*de1e4e89SAndroid Build Coastguard Worker if (ntohl(key->mask) == 0x00ff0000) {
905*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n match IP protocol %d",
906*de1e4e89SAndroid Build Coastguard Worker ntohl(key->val) >> 16);
907*de1e4e89SAndroid Build Coastguard Worker return;
908*de1e4e89SAndroid Build Coastguard Worker }
909*de1e4e89SAndroid Build Coastguard Worker break;
910*de1e4e89SAndroid Build Coastguard Worker case 12:
911*de1e4e89SAndroid Build Coastguard Worker case 16: {
912*de1e4e89SAndroid Build Coastguard Worker int bits = mask2bits(key->mask);
913*de1e4e89SAndroid Build Coastguard Worker
914*de1e4e89SAndroid Build Coastguard Worker if (bits >= 0) {
915*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n %s %s/%d",
916*de1e4e89SAndroid Build Coastguard Worker key->off == 12 ? "match IP src" : "match IP dst",
917*de1e4e89SAndroid Build Coastguard Worker inet_ntop(AF_INET, &key->val,
918*de1e4e89SAndroid Build Coastguard Worker abuf, sizeof(abuf)),
919*de1e4e89SAndroid Build Coastguard Worker bits);
920*de1e4e89SAndroid Build Coastguard Worker return;
921*de1e4e89SAndroid Build Coastguard Worker }
922*de1e4e89SAndroid Build Coastguard Worker }
923*de1e4e89SAndroid Build Coastguard Worker break;
924*de1e4e89SAndroid Build Coastguard Worker
925*de1e4e89SAndroid Build Coastguard Worker case 20:
926*de1e4e89SAndroid Build Coastguard Worker switch (ntohl(key->mask)) {
927*de1e4e89SAndroid Build Coastguard Worker case 0x0000ffff:
928*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n match sport %u",
929*de1e4e89SAndroid Build Coastguard Worker ntohl(key->val) & 0xffff);
930*de1e4e89SAndroid Build Coastguard Worker return;
931*de1e4e89SAndroid Build Coastguard Worker case 0xffff0000:
932*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n match dport %u",
933*de1e4e89SAndroid Build Coastguard Worker ntohl(key->val) >> 16);
934*de1e4e89SAndroid Build Coastguard Worker return;
935*de1e4e89SAndroid Build Coastguard Worker case 0xffffffff:
936*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n match sport %u, match dport %u",
937*de1e4e89SAndroid Build Coastguard Worker ntohl(key->val) & 0xffff,
938*de1e4e89SAndroid Build Coastguard Worker ntohl(key->val) >> 16);
939*de1e4e89SAndroid Build Coastguard Worker
940*de1e4e89SAndroid Build Coastguard Worker return;
941*de1e4e89SAndroid Build Coastguard Worker }
942*de1e4e89SAndroid Build Coastguard Worker /* XXX: Default print_raw */
943*de1e4e89SAndroid Build Coastguard Worker }
944*de1e4e89SAndroid Build Coastguard Worker }
945*de1e4e89SAndroid Build Coastguard Worker
print_raw(FILE * f,const struct tc_u32_key * key)946*de1e4e89SAndroid Build Coastguard Worker static void print_raw(FILE *f, const struct tc_u32_key *key)
947*de1e4e89SAndroid Build Coastguard Worker {
948*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n match %08x/%08x at %s%d",
949*de1e4e89SAndroid Build Coastguard Worker (unsigned int)ntohl(key->val),
950*de1e4e89SAndroid Build Coastguard Worker (unsigned int)ntohl(key->mask),
951*de1e4e89SAndroid Build Coastguard Worker key->offmask ? "nexthdr+" : "",
952*de1e4e89SAndroid Build Coastguard Worker key->off);
953*de1e4e89SAndroid Build Coastguard Worker }
954*de1e4e89SAndroid Build Coastguard Worker
955*de1e4e89SAndroid Build Coastguard Worker static const struct {
956*de1e4e89SAndroid Build Coastguard Worker __u16 proto;
957*de1e4e89SAndroid Build Coastguard Worker __u16 pad;
958*de1e4e89SAndroid Build Coastguard Worker void (*pprinter)(FILE *f, const struct tc_u32_key *key);
959*de1e4e89SAndroid Build Coastguard Worker } u32_pprinters[] = {
960*de1e4e89SAndroid Build Coastguard Worker {0, 0, print_raw},
961*de1e4e89SAndroid Build Coastguard Worker {ETH_P_IP, 0, print_ipv4},
962*de1e4e89SAndroid Build Coastguard Worker {ETH_P_IPV6, 0, print_ipv6},
963*de1e4e89SAndroid Build Coastguard Worker };
964*de1e4e89SAndroid Build Coastguard Worker
show_keys(FILE * f,const struct tc_u32_key * key)965*de1e4e89SAndroid Build Coastguard Worker static void show_keys(FILE *f, const struct tc_u32_key *key)
966*de1e4e89SAndroid Build Coastguard Worker {
967*de1e4e89SAndroid Build Coastguard Worker int i = 0;
968*de1e4e89SAndroid Build Coastguard Worker
969*de1e4e89SAndroid Build Coastguard Worker if (!show_pretty)
970*de1e4e89SAndroid Build Coastguard Worker goto show_k;
971*de1e4e89SAndroid Build Coastguard Worker
972*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(u32_pprinters); i++) {
973*de1e4e89SAndroid Build Coastguard Worker if (u32_pprinters[i].proto == ntohs(f_proto)) {
974*de1e4e89SAndroid Build Coastguard Worker show_k:
975*de1e4e89SAndroid Build Coastguard Worker u32_pprinters[i].pprinter(f, key);
976*de1e4e89SAndroid Build Coastguard Worker return;
977*de1e4e89SAndroid Build Coastguard Worker }
978*de1e4e89SAndroid Build Coastguard Worker }
979*de1e4e89SAndroid Build Coastguard Worker
980*de1e4e89SAndroid Build Coastguard Worker i = 0;
981*de1e4e89SAndroid Build Coastguard Worker goto show_k;
982*de1e4e89SAndroid Build Coastguard Worker }
983*de1e4e89SAndroid Build Coastguard Worker
u32_parse_opt(struct filter_util * qu,char * handle,int argc,char ** argv,struct nlmsghdr * n)984*de1e4e89SAndroid Build Coastguard Worker static int u32_parse_opt(struct filter_util *qu, char *handle,
985*de1e4e89SAndroid Build Coastguard Worker int argc, char **argv, struct nlmsghdr *n)
986*de1e4e89SAndroid Build Coastguard Worker {
987*de1e4e89SAndroid Build Coastguard Worker struct {
988*de1e4e89SAndroid Build Coastguard Worker struct tc_u32_sel sel;
989*de1e4e89SAndroid Build Coastguard Worker struct tc_u32_key keys[128];
990*de1e4e89SAndroid Build Coastguard Worker } sel = {};
991*de1e4e89SAndroid Build Coastguard Worker struct tcmsg *t = NLMSG_DATA(n);
992*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tail;
993*de1e4e89SAndroid Build Coastguard Worker int sel_ok = 0, terminal_ok = 0;
994*de1e4e89SAndroid Build Coastguard Worker int sample_ok = 0;
995*de1e4e89SAndroid Build Coastguard Worker __u32 htid = 0;
996*de1e4e89SAndroid Build Coastguard Worker __u32 order = 0;
997*de1e4e89SAndroid Build Coastguard Worker __u32 flags = 0;
998*de1e4e89SAndroid Build Coastguard Worker
999*de1e4e89SAndroid Build Coastguard Worker if (handle && get_u32_handle(&t->tcm_handle, handle)) {
1000*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal filter ID\n");
1001*de1e4e89SAndroid Build Coastguard Worker return -1;
1002*de1e4e89SAndroid Build Coastguard Worker }
1003*de1e4e89SAndroid Build Coastguard Worker
1004*de1e4e89SAndroid Build Coastguard Worker if (argc == 0)
1005*de1e4e89SAndroid Build Coastguard Worker return 0;
1006*de1e4e89SAndroid Build Coastguard Worker
1007*de1e4e89SAndroid Build Coastguard Worker tail = NLMSG_TAIL(n);
1008*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
1009*de1e4e89SAndroid Build Coastguard Worker
1010*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
1011*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "match") == 0) {
1012*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1013*de1e4e89SAndroid Build Coastguard Worker if (parse_selector(&argc, &argv, &sel.sel, n)) {
1014*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"match\"\n");
1015*de1e4e89SAndroid Build Coastguard Worker return -1;
1016*de1e4e89SAndroid Build Coastguard Worker }
1017*de1e4e89SAndroid Build Coastguard Worker sel_ok++;
1018*de1e4e89SAndroid Build Coastguard Worker continue;
1019*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "offset") == 0) {
1020*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1021*de1e4e89SAndroid Build Coastguard Worker if (parse_offset(&argc, &argv, &sel.sel)) {
1022*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"offset\"\n");
1023*de1e4e89SAndroid Build Coastguard Worker return -1;
1024*de1e4e89SAndroid Build Coastguard Worker }
1025*de1e4e89SAndroid Build Coastguard Worker continue;
1026*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "hashkey") == 0) {
1027*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1028*de1e4e89SAndroid Build Coastguard Worker if (parse_hashkey(&argc, &argv, &sel.sel)) {
1029*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"hashkey\"\n");
1030*de1e4e89SAndroid Build Coastguard Worker return -1;
1031*de1e4e89SAndroid Build Coastguard Worker }
1032*de1e4e89SAndroid Build Coastguard Worker continue;
1033*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "classid") == 0 ||
1034*de1e4e89SAndroid Build Coastguard Worker strcmp(*argv, "flowid") == 0) {
1035*de1e4e89SAndroid Build Coastguard Worker unsigned int flowid;
1036*de1e4e89SAndroid Build Coastguard Worker
1037*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1038*de1e4e89SAndroid Build Coastguard Worker if (get_tc_classid(&flowid, *argv)) {
1039*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"classid\"\n");
1040*de1e4e89SAndroid Build Coastguard Worker return -1;
1041*de1e4e89SAndroid Build Coastguard Worker }
1042*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_U32_CLASSID, &flowid, 4);
1043*de1e4e89SAndroid Build Coastguard Worker sel.sel.flags |= TC_U32_TERMINAL;
1044*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "divisor") == 0) {
1045*de1e4e89SAndroid Build Coastguard Worker unsigned int divisor;
1046*de1e4e89SAndroid Build Coastguard Worker
1047*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1048*de1e4e89SAndroid Build Coastguard Worker if (get_unsigned(&divisor, *argv, 0) ||
1049*de1e4e89SAndroid Build Coastguard Worker divisor == 0 ||
1050*de1e4e89SAndroid Build Coastguard Worker divisor > 0x100 || ((divisor - 1) & divisor)) {
1051*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"divisor\"\n");
1052*de1e4e89SAndroid Build Coastguard Worker return -1;
1053*de1e4e89SAndroid Build Coastguard Worker }
1054*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_U32_DIVISOR, &divisor, 4);
1055*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "order") == 0) {
1056*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1057*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&order, *argv, 0)) {
1058*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"order\"\n");
1059*de1e4e89SAndroid Build Coastguard Worker return -1;
1060*de1e4e89SAndroid Build Coastguard Worker }
1061*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "link") == 0) {
1062*de1e4e89SAndroid Build Coastguard Worker unsigned int linkid;
1063*de1e4e89SAndroid Build Coastguard Worker
1064*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1065*de1e4e89SAndroid Build Coastguard Worker if (get_u32_handle(&linkid, *argv)) {
1066*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"link\"\n");
1067*de1e4e89SAndroid Build Coastguard Worker return -1;
1068*de1e4e89SAndroid Build Coastguard Worker }
1069*de1e4e89SAndroid Build Coastguard Worker if (linkid && TC_U32_NODE(linkid)) {
1070*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\"link\" must be a hash table.\n");
1071*de1e4e89SAndroid Build Coastguard Worker return -1;
1072*de1e4e89SAndroid Build Coastguard Worker }
1073*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_U32_LINK, &linkid, 4);
1074*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "ht") == 0) {
1075*de1e4e89SAndroid Build Coastguard Worker unsigned int ht;
1076*de1e4e89SAndroid Build Coastguard Worker
1077*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1078*de1e4e89SAndroid Build Coastguard Worker if (get_u32_handle(&ht, *argv)) {
1079*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"ht\"\n");
1080*de1e4e89SAndroid Build Coastguard Worker return -1;
1081*de1e4e89SAndroid Build Coastguard Worker }
1082*de1e4e89SAndroid Build Coastguard Worker if (handle && TC_U32_NODE(ht)) {
1083*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\"ht\" must be a hash table.\n");
1084*de1e4e89SAndroid Build Coastguard Worker return -1;
1085*de1e4e89SAndroid Build Coastguard Worker }
1086*de1e4e89SAndroid Build Coastguard Worker if (sample_ok)
1087*de1e4e89SAndroid Build Coastguard Worker htid = (htid & 0xFF000) | (ht & 0xFFF00000);
1088*de1e4e89SAndroid Build Coastguard Worker else
1089*de1e4e89SAndroid Build Coastguard Worker htid = (ht & 0xFFFFF000);
1090*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "sample") == 0) {
1091*de1e4e89SAndroid Build Coastguard Worker __u32 hash;
1092*de1e4e89SAndroid Build Coastguard Worker unsigned int divisor = 0x100;
1093*de1e4e89SAndroid Build Coastguard Worker struct {
1094*de1e4e89SAndroid Build Coastguard Worker struct tc_u32_sel sel;
1095*de1e4e89SAndroid Build Coastguard Worker struct tc_u32_key keys[4];
1096*de1e4e89SAndroid Build Coastguard Worker } sel2 = {};
1097*de1e4e89SAndroid Build Coastguard Worker
1098*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1099*de1e4e89SAndroid Build Coastguard Worker if (parse_selector(&argc, &argv, &sel2.sel, n)) {
1100*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"sample\"\n");
1101*de1e4e89SAndroid Build Coastguard Worker return -1;
1102*de1e4e89SAndroid Build Coastguard Worker }
1103*de1e4e89SAndroid Build Coastguard Worker if (sel2.sel.nkeys != 1) {
1104*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\"sample\" must contain exactly ONE key.\n");
1105*de1e4e89SAndroid Build Coastguard Worker return -1;
1106*de1e4e89SAndroid Build Coastguard Worker }
1107*de1e4e89SAndroid Build Coastguard Worker if (*argv != 0 && strcmp(*argv, "divisor") == 0) {
1108*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1109*de1e4e89SAndroid Build Coastguard Worker if (get_unsigned(&divisor, *argv, 0) ||
1110*de1e4e89SAndroid Build Coastguard Worker divisor == 0 || divisor > 0x100 ||
1111*de1e4e89SAndroid Build Coastguard Worker ((divisor - 1) & divisor)) {
1112*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal sample \"divisor\"\n");
1113*de1e4e89SAndroid Build Coastguard Worker return -1;
1114*de1e4e89SAndroid Build Coastguard Worker }
1115*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1116*de1e4e89SAndroid Build Coastguard Worker }
1117*de1e4e89SAndroid Build Coastguard Worker hash = sel2.sel.keys[0].val & sel2.sel.keys[0].mask;
1118*de1e4e89SAndroid Build Coastguard Worker hash ^= hash >> 16;
1119*de1e4e89SAndroid Build Coastguard Worker hash ^= hash >> 8;
1120*de1e4e89SAndroid Build Coastguard Worker htid = ((hash % divisor) << 12) | (htid & 0xFFF00000);
1121*de1e4e89SAndroid Build Coastguard Worker sample_ok = 1;
1122*de1e4e89SAndroid Build Coastguard Worker continue;
1123*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "indev") == 0) {
1124*de1e4e89SAndroid Build Coastguard Worker char ind[IFNAMSIZ + 1] = {};
1125*de1e4e89SAndroid Build Coastguard Worker
1126*de1e4e89SAndroid Build Coastguard Worker argc--;
1127*de1e4e89SAndroid Build Coastguard Worker argv++;
1128*de1e4e89SAndroid Build Coastguard Worker if (argc < 1) {
1129*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal indev\n");
1130*de1e4e89SAndroid Build Coastguard Worker return -1;
1131*de1e4e89SAndroid Build Coastguard Worker }
1132*de1e4e89SAndroid Build Coastguard Worker strncpy(ind, *argv, sizeof(ind) - 1);
1133*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_U32_INDEV, ind,
1134*de1e4e89SAndroid Build Coastguard Worker strlen(ind) + 1);
1135*de1e4e89SAndroid Build Coastguard Worker
1136*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "action") == 0) {
1137*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1138*de1e4e89SAndroid Build Coastguard Worker if (parse_action(&argc, &argv, TCA_U32_ACT, n)) {
1139*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"action\"\n");
1140*de1e4e89SAndroid Build Coastguard Worker return -1;
1141*de1e4e89SAndroid Build Coastguard Worker }
1142*de1e4e89SAndroid Build Coastguard Worker terminal_ok++;
1143*de1e4e89SAndroid Build Coastguard Worker continue;
1144*de1e4e89SAndroid Build Coastguard Worker
1145*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "police") == 0) {
1146*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1147*de1e4e89SAndroid Build Coastguard Worker if (parse_police(&argc, &argv, TCA_U32_POLICE, n)) {
1148*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"police\"\n");
1149*de1e4e89SAndroid Build Coastguard Worker return -1;
1150*de1e4e89SAndroid Build Coastguard Worker }
1151*de1e4e89SAndroid Build Coastguard Worker terminal_ok++;
1152*de1e4e89SAndroid Build Coastguard Worker continue;
1153*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "skip_hw") == 0) {
1154*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1155*de1e4e89SAndroid Build Coastguard Worker flags |= TCA_CLS_FLAGS_SKIP_HW;
1156*de1e4e89SAndroid Build Coastguard Worker continue;
1157*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "skip_sw") == 0) {
1158*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1159*de1e4e89SAndroid Build Coastguard Worker flags |= TCA_CLS_FLAGS_SKIP_SW;
1160*de1e4e89SAndroid Build Coastguard Worker continue;
1161*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "help") == 0) {
1162*de1e4e89SAndroid Build Coastguard Worker explain();
1163*de1e4e89SAndroid Build Coastguard Worker return -1;
1164*de1e4e89SAndroid Build Coastguard Worker } else {
1165*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "What is \"%s\"?\n", *argv);
1166*de1e4e89SAndroid Build Coastguard Worker explain();
1167*de1e4e89SAndroid Build Coastguard Worker return -1;
1168*de1e4e89SAndroid Build Coastguard Worker }
1169*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
1170*de1e4e89SAndroid Build Coastguard Worker }
1171*de1e4e89SAndroid Build Coastguard Worker
1172*de1e4e89SAndroid Build Coastguard Worker /* We dont necessarily need class/flowids */
1173*de1e4e89SAndroid Build Coastguard Worker if (terminal_ok)
1174*de1e4e89SAndroid Build Coastguard Worker sel.sel.flags |= TC_U32_TERMINAL;
1175*de1e4e89SAndroid Build Coastguard Worker
1176*de1e4e89SAndroid Build Coastguard Worker if (order) {
1177*de1e4e89SAndroid Build Coastguard Worker if (TC_U32_NODE(t->tcm_handle) &&
1178*de1e4e89SAndroid Build Coastguard Worker order != TC_U32_NODE(t->tcm_handle)) {
1179*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\"order\" contradicts \"handle\"\n");
1180*de1e4e89SAndroid Build Coastguard Worker return -1;
1181*de1e4e89SAndroid Build Coastguard Worker }
1182*de1e4e89SAndroid Build Coastguard Worker t->tcm_handle |= order;
1183*de1e4e89SAndroid Build Coastguard Worker }
1184*de1e4e89SAndroid Build Coastguard Worker
1185*de1e4e89SAndroid Build Coastguard Worker if (htid)
1186*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_U32_HASH, &htid, 4);
1187*de1e4e89SAndroid Build Coastguard Worker if (sel_ok)
1188*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_U32_SEL, &sel,
1189*de1e4e89SAndroid Build Coastguard Worker sizeof(sel.sel) +
1190*de1e4e89SAndroid Build Coastguard Worker sel.sel.nkeys * sizeof(struct tc_u32_key));
1191*de1e4e89SAndroid Build Coastguard Worker if (flags) {
1192*de1e4e89SAndroid Build Coastguard Worker if (!(flags ^ (TCA_CLS_FLAGS_SKIP_HW |
1193*de1e4e89SAndroid Build Coastguard Worker TCA_CLS_FLAGS_SKIP_SW))) {
1194*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
1195*de1e4e89SAndroid Build Coastguard Worker "skip_hw and skip_sw are mutually exclusive\n");
1196*de1e4e89SAndroid Build Coastguard Worker return -1;
1197*de1e4e89SAndroid Build Coastguard Worker }
1198*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_U32_FLAGS, &flags, 4);
1199*de1e4e89SAndroid Build Coastguard Worker }
1200*de1e4e89SAndroid Build Coastguard Worker
1201*de1e4e89SAndroid Build Coastguard Worker tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
1202*de1e4e89SAndroid Build Coastguard Worker return 0;
1203*de1e4e89SAndroid Build Coastguard Worker }
1204*de1e4e89SAndroid Build Coastguard Worker
u32_print_opt(struct filter_util * qu,FILE * f,struct rtattr * opt,__u32 handle)1205*de1e4e89SAndroid Build Coastguard Worker static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
1206*de1e4e89SAndroid Build Coastguard Worker __u32 handle)
1207*de1e4e89SAndroid Build Coastguard Worker {
1208*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tb[TCA_U32_MAX + 1];
1209*de1e4e89SAndroid Build Coastguard Worker struct tc_u32_sel *sel = NULL;
1210*de1e4e89SAndroid Build Coastguard Worker struct tc_u32_pcnt *pf = NULL;
1211*de1e4e89SAndroid Build Coastguard Worker
1212*de1e4e89SAndroid Build Coastguard Worker if (opt == NULL)
1213*de1e4e89SAndroid Build Coastguard Worker return 0;
1214*de1e4e89SAndroid Build Coastguard Worker
1215*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(tb, TCA_U32_MAX, opt);
1216*de1e4e89SAndroid Build Coastguard Worker
1217*de1e4e89SAndroid Build Coastguard Worker if (handle) {
1218*de1e4e89SAndroid Build Coastguard Worker SPRINT_BUF(b1);
1219*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "fh %s ", sprint_u32_handle(handle, b1));
1220*de1e4e89SAndroid Build Coastguard Worker }
1221*de1e4e89SAndroid Build Coastguard Worker
1222*de1e4e89SAndroid Build Coastguard Worker if (TC_U32_NODE(handle))
1223*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "order %d ", TC_U32_NODE(handle));
1224*de1e4e89SAndroid Build Coastguard Worker
1225*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_U32_SEL]) {
1226*de1e4e89SAndroid Build Coastguard Worker if (RTA_PAYLOAD(tb[TCA_U32_SEL]) < sizeof(*sel))
1227*de1e4e89SAndroid Build Coastguard Worker return -1;
1228*de1e4e89SAndroid Build Coastguard Worker
1229*de1e4e89SAndroid Build Coastguard Worker sel = RTA_DATA(tb[TCA_U32_SEL]);
1230*de1e4e89SAndroid Build Coastguard Worker }
1231*de1e4e89SAndroid Build Coastguard Worker
1232*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_U32_DIVISOR]) {
1233*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "ht divisor %d ",
1234*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u32(tb[TCA_U32_DIVISOR]));
1235*de1e4e89SAndroid Build Coastguard Worker } else if (tb[TCA_U32_HASH]) {
1236*de1e4e89SAndroid Build Coastguard Worker __u32 htid = rta_getattr_u32(tb[TCA_U32_HASH]);
1237*de1e4e89SAndroid Build Coastguard Worker
1238*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "key ht %x bkt %x ", TC_U32_USERHTID(htid),
1239*de1e4e89SAndroid Build Coastguard Worker TC_U32_HASH(htid));
1240*de1e4e89SAndroid Build Coastguard Worker } else {
1241*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "??? ");
1242*de1e4e89SAndroid Build Coastguard Worker }
1243*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_U32_CLASSID]) {
1244*de1e4e89SAndroid Build Coastguard Worker SPRINT_BUF(b1);
1245*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "%sflowid %s ",
1246*de1e4e89SAndroid Build Coastguard Worker !sel || !(sel->flags & TC_U32_TERMINAL) ? "*" : "",
1247*de1e4e89SAndroid Build Coastguard Worker sprint_tc_classid(rta_getattr_u32(tb[TCA_U32_CLASSID]),
1248*de1e4e89SAndroid Build Coastguard Worker b1));
1249*de1e4e89SAndroid Build Coastguard Worker } else if (sel && sel->flags & TC_U32_TERMINAL) {
1250*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "terminal flowid ??? ");
1251*de1e4e89SAndroid Build Coastguard Worker }
1252*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_U32_LINK]) {
1253*de1e4e89SAndroid Build Coastguard Worker SPRINT_BUF(b1);
1254*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "link %s ",
1255*de1e4e89SAndroid Build Coastguard Worker sprint_u32_handle(rta_getattr_u32(tb[TCA_U32_LINK]),
1256*de1e4e89SAndroid Build Coastguard Worker b1));
1257*de1e4e89SAndroid Build Coastguard Worker }
1258*de1e4e89SAndroid Build Coastguard Worker
1259*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_U32_FLAGS]) {
1260*de1e4e89SAndroid Build Coastguard Worker __u32 flags = rta_getattr_u32(tb[TCA_U32_FLAGS]);
1261*de1e4e89SAndroid Build Coastguard Worker
1262*de1e4e89SAndroid Build Coastguard Worker if (flags & TCA_CLS_FLAGS_SKIP_HW)
1263*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "skip_hw ");
1264*de1e4e89SAndroid Build Coastguard Worker if (flags & TCA_CLS_FLAGS_SKIP_SW)
1265*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "skip_sw ");
1266*de1e4e89SAndroid Build Coastguard Worker
1267*de1e4e89SAndroid Build Coastguard Worker if (flags & TCA_CLS_FLAGS_IN_HW)
1268*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "in_hw ");
1269*de1e4e89SAndroid Build Coastguard Worker else if (flags & TCA_CLS_FLAGS_NOT_IN_HW)
1270*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "not_in_hw ");
1271*de1e4e89SAndroid Build Coastguard Worker }
1272*de1e4e89SAndroid Build Coastguard Worker
1273*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_U32_PCNT]) {
1274*de1e4e89SAndroid Build Coastguard Worker if (RTA_PAYLOAD(tb[TCA_U32_PCNT]) < sizeof(*pf)) {
1275*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "Broken perf counters\n");
1276*de1e4e89SAndroid Build Coastguard Worker return -1;
1277*de1e4e89SAndroid Build Coastguard Worker }
1278*de1e4e89SAndroid Build Coastguard Worker pf = RTA_DATA(tb[TCA_U32_PCNT]);
1279*de1e4e89SAndroid Build Coastguard Worker }
1280*de1e4e89SAndroid Build Coastguard Worker
1281*de1e4e89SAndroid Build Coastguard Worker if (sel && show_stats && NULL != pf)
1282*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " (rule hit %llu success %llu)",
1283*de1e4e89SAndroid Build Coastguard Worker (unsigned long long) pf->rcnt,
1284*de1e4e89SAndroid Build Coastguard Worker (unsigned long long) pf->rhit);
1285*de1e4e89SAndroid Build Coastguard Worker
1286*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_U32_MARK]) {
1287*de1e4e89SAndroid Build Coastguard Worker struct tc_u32_mark *mark = RTA_DATA(tb[TCA_U32_MARK]);
1288*de1e4e89SAndroid Build Coastguard Worker
1289*de1e4e89SAndroid Build Coastguard Worker if (RTA_PAYLOAD(tb[TCA_U32_MARK]) < sizeof(*mark)) {
1290*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n Invalid mark (kernel&iproute2 mismatch)\n");
1291*de1e4e89SAndroid Build Coastguard Worker } else {
1292*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n mark 0x%04x 0x%04x (success %d)",
1293*de1e4e89SAndroid Build Coastguard Worker mark->val, mark->mask, mark->success);
1294*de1e4e89SAndroid Build Coastguard Worker }
1295*de1e4e89SAndroid Build Coastguard Worker }
1296*de1e4e89SAndroid Build Coastguard Worker
1297*de1e4e89SAndroid Build Coastguard Worker if (sel) {
1298*de1e4e89SAndroid Build Coastguard Worker if (sel->nkeys) {
1299*de1e4e89SAndroid Build Coastguard Worker int i;
1300*de1e4e89SAndroid Build Coastguard Worker
1301*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < sel->nkeys; i++) {
1302*de1e4e89SAndroid Build Coastguard Worker show_keys(f, sel->keys + i);
1303*de1e4e89SAndroid Build Coastguard Worker if (show_stats && NULL != pf)
1304*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " (success %llu ) ",
1305*de1e4e89SAndroid Build Coastguard Worker (unsigned long long) pf->kcnts[i]);
1306*de1e4e89SAndroid Build Coastguard Worker }
1307*de1e4e89SAndroid Build Coastguard Worker }
1308*de1e4e89SAndroid Build Coastguard Worker
1309*de1e4e89SAndroid Build Coastguard Worker if (sel->flags & (TC_U32_VAROFFSET | TC_U32_OFFSET)) {
1310*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n offset ");
1311*de1e4e89SAndroid Build Coastguard Worker if (sel->flags & TC_U32_VAROFFSET)
1312*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "%04x>>%d at %d ",
1313*de1e4e89SAndroid Build Coastguard Worker ntohs(sel->offmask),
1314*de1e4e89SAndroid Build Coastguard Worker sel->offshift, sel->offoff);
1315*de1e4e89SAndroid Build Coastguard Worker if (sel->off)
1316*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "plus %d ", sel->off);
1317*de1e4e89SAndroid Build Coastguard Worker }
1318*de1e4e89SAndroid Build Coastguard Worker if (sel->flags & TC_U32_EAT)
1319*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " eat ");
1320*de1e4e89SAndroid Build Coastguard Worker
1321*de1e4e89SAndroid Build Coastguard Worker if (sel->hmask) {
1322*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n hash mask %08x at %d ",
1323*de1e4e89SAndroid Build Coastguard Worker (unsigned int)htonl(sel->hmask), sel->hoff);
1324*de1e4e89SAndroid Build Coastguard Worker }
1325*de1e4e89SAndroid Build Coastguard Worker }
1326*de1e4e89SAndroid Build Coastguard Worker
1327*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_U32_POLICE]) {
1328*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n");
1329*de1e4e89SAndroid Build Coastguard Worker tc_print_police(f, tb[TCA_U32_POLICE]);
1330*de1e4e89SAndroid Build Coastguard Worker }
1331*de1e4e89SAndroid Build Coastguard Worker
1332*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_U32_INDEV]) {
1333*de1e4e89SAndroid Build Coastguard Worker struct rtattr *idev = tb[TCA_U32_INDEV];
1334*de1e4e89SAndroid Build Coastguard Worker
1335*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n input dev %s\n", rta_getattr_str(idev));
1336*de1e4e89SAndroid Build Coastguard Worker }
1337*de1e4e89SAndroid Build Coastguard Worker
1338*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_U32_ACT])
1339*de1e4e89SAndroid Build Coastguard Worker tc_print_action(f, tb[TCA_U32_ACT], 0);
1340*de1e4e89SAndroid Build Coastguard Worker
1341*de1e4e89SAndroid Build Coastguard Worker return 0;
1342*de1e4e89SAndroid Build Coastguard Worker }
1343*de1e4e89SAndroid Build Coastguard Worker
1344*de1e4e89SAndroid Build Coastguard Worker struct filter_util u32_filter_util = {
1345*de1e4e89SAndroid Build Coastguard Worker .id = "u32",
1346*de1e4e89SAndroid Build Coastguard Worker .parse_fopt = u32_parse_opt,
1347*de1e4e89SAndroid Build Coastguard Worker .print_fopt = u32_print_opt,
1348*de1e4e89SAndroid Build Coastguard Worker };
1349