1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * m_pedit.c generic packet editor actions module
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can distribute 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: J Hadi Salim ([email protected])
10*de1e4e89SAndroid Build Coastguard Worker *
11*de1e4e89SAndroid Build Coastguard Worker * TODO:
12*de1e4e89SAndroid Build Coastguard Worker * 1) Big endian broken in some spots
13*de1e4e89SAndroid Build Coastguard Worker * 2) A lot of this stuff was added on the fly; get a big double-double
14*de1e4e89SAndroid Build Coastguard Worker * and clean it up at some point.
15*de1e4e89SAndroid Build Coastguard Worker *
16*de1e4e89SAndroid Build Coastguard Worker */
17*de1e4e89SAndroid Build Coastguard Worker
18*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <syslog.h>
22*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
23*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
24*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
25*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
26*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
27*de1e4e89SAndroid Build Coastguard Worker #include <dlfcn.h>
28*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
29*de1e4e89SAndroid Build Coastguard Worker #include "tc_util.h"
30*de1e4e89SAndroid Build Coastguard Worker #include "m_pedit.h"
31*de1e4e89SAndroid Build Coastguard Worker #include "rt_names.h"
32*de1e4e89SAndroid Build Coastguard Worker
33*de1e4e89SAndroid Build Coastguard Worker static struct m_pedit_util *pedit_list;
34*de1e4e89SAndroid Build Coastguard Worker static int pedit_debug;
35*de1e4e89SAndroid Build Coastguard Worker
explain(void)36*de1e4e89SAndroid Build Coastguard Worker static void explain(void)
37*de1e4e89SAndroid Build Coastguard Worker {
38*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Usage: ... pedit munge [ex] <MUNGE> [CONTROL]\n");
39*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
40*de1e4e89SAndroid Build Coastguard Worker "Where: MUNGE := <RAW>|<LAYERED>\n"
41*de1e4e89SAndroid Build Coastguard Worker "\t<RAW>:= <OFFSETC>[ATC]<CMD>\n \t\tOFFSETC:= offset <offval> <u8|u16|u32>\n"
42*de1e4e89SAndroid Build Coastguard Worker "\t\tATC:= at <atval> offmask <maskval> shift <shiftval>\n"
43*de1e4e89SAndroid Build Coastguard Worker "\t\tNOTE: offval is byte offset, must be multiple of 4\n"
44*de1e4e89SAndroid Build Coastguard Worker "\t\tNOTE: maskval is a 32 bit hex number\n \t\tNOTE: shiftval is a shift value\n"
45*de1e4e89SAndroid Build Coastguard Worker "\t\tCMD:= clear | invert | set <setval>| add <addval> | retain\n"
46*de1e4e89SAndroid Build Coastguard Worker "\t<LAYERED>:= ip <ipdata> | ip6 <ip6data>\n"
47*de1e4e89SAndroid Build Coastguard Worker " \t\t| udp <udpdata> | tcp <tcpdata> | icmp <icmpdata>\n"
48*de1e4e89SAndroid Build Coastguard Worker "\tCONTROL:= reclassify | pipe | drop | continue | pass |\n"
49*de1e4e89SAndroid Build Coastguard Worker "\t goto chain <CHAIN_INDEX>\n"
50*de1e4e89SAndroid Build Coastguard Worker "\tNOTE: if 'ex' is set, extended functionality will be supported (kernel >= 4.11)\n"
51*de1e4e89SAndroid Build Coastguard Worker "For Example usage look at the examples directory\n");
52*de1e4e89SAndroid Build Coastguard Worker
53*de1e4e89SAndroid Build Coastguard Worker }
54*de1e4e89SAndroid Build Coastguard Worker
usage(void)55*de1e4e89SAndroid Build Coastguard Worker static void usage(void)
56*de1e4e89SAndroid Build Coastguard Worker {
57*de1e4e89SAndroid Build Coastguard Worker explain();
58*de1e4e89SAndroid Build Coastguard Worker exit(-1);
59*de1e4e89SAndroid Build Coastguard Worker }
60*de1e4e89SAndroid Build Coastguard Worker
pedit_parse_nopopt(int * argc_p,char *** argv_p,struct m_pedit_sel * sel,struct m_pedit_key * tkey)61*de1e4e89SAndroid Build Coastguard Worker static int pedit_parse_nopopt(int *argc_p, char ***argv_p,
62*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_sel *sel,
63*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_key *tkey)
64*de1e4e89SAndroid Build Coastguard Worker {
65*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
66*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
67*de1e4e89SAndroid Build Coastguard Worker
68*de1e4e89SAndroid Build Coastguard Worker if (argc) {
69*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
70*de1e4e89SAndroid Build Coastguard Worker "Unknown action hence option \"%s\" is unparsable\n",
71*de1e4e89SAndroid Build Coastguard Worker *argv);
72*de1e4e89SAndroid Build Coastguard Worker return -1;
73*de1e4e89SAndroid Build Coastguard Worker }
74*de1e4e89SAndroid Build Coastguard Worker
75*de1e4e89SAndroid Build Coastguard Worker return 0;
76*de1e4e89SAndroid Build Coastguard Worker
77*de1e4e89SAndroid Build Coastguard Worker }
78*de1e4e89SAndroid Build Coastguard Worker
get_pedit_kind(const char * str)79*de1e4e89SAndroid Build Coastguard Worker static struct m_pedit_util *get_pedit_kind(const char *str)
80*de1e4e89SAndroid Build Coastguard Worker {
81*de1e4e89SAndroid Build Coastguard Worker static void *pBODY;
82*de1e4e89SAndroid Build Coastguard Worker void *dlh;
83*de1e4e89SAndroid Build Coastguard Worker char buf[256];
84*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_util *p;
85*de1e4e89SAndroid Build Coastguard Worker
86*de1e4e89SAndroid Build Coastguard Worker for (p = pedit_list; p; p = p->next) {
87*de1e4e89SAndroid Build Coastguard Worker if (strcmp(p->id, str) == 0)
88*de1e4e89SAndroid Build Coastguard Worker return p;
89*de1e4e89SAndroid Build Coastguard Worker }
90*de1e4e89SAndroid Build Coastguard Worker
91*de1e4e89SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "p_%s.so", str);
92*de1e4e89SAndroid Build Coastguard Worker dlh = dlopen(buf, RTLD_LAZY);
93*de1e4e89SAndroid Build Coastguard Worker if (dlh == NULL) {
94*de1e4e89SAndroid Build Coastguard Worker dlh = pBODY;
95*de1e4e89SAndroid Build Coastguard Worker if (dlh == NULL) {
96*de1e4e89SAndroid Build Coastguard Worker dlh = pBODY = dlopen(NULL, RTLD_LAZY);
97*de1e4e89SAndroid Build Coastguard Worker if (dlh == NULL)
98*de1e4e89SAndroid Build Coastguard Worker goto noexist;
99*de1e4e89SAndroid Build Coastguard Worker }
100*de1e4e89SAndroid Build Coastguard Worker }
101*de1e4e89SAndroid Build Coastguard Worker
102*de1e4e89SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "p_pedit_%s", str);
103*de1e4e89SAndroid Build Coastguard Worker p = dlsym(dlh, buf);
104*de1e4e89SAndroid Build Coastguard Worker if (p == NULL)
105*de1e4e89SAndroid Build Coastguard Worker goto noexist;
106*de1e4e89SAndroid Build Coastguard Worker
107*de1e4e89SAndroid Build Coastguard Worker reg:
108*de1e4e89SAndroid Build Coastguard Worker p->next = pedit_list;
109*de1e4e89SAndroid Build Coastguard Worker pedit_list = p;
110*de1e4e89SAndroid Build Coastguard Worker return p;
111*de1e4e89SAndroid Build Coastguard Worker
112*de1e4e89SAndroid Build Coastguard Worker noexist:
113*de1e4e89SAndroid Build Coastguard Worker p = calloc(1, sizeof(*p));
114*de1e4e89SAndroid Build Coastguard Worker if (p) {
115*de1e4e89SAndroid Build Coastguard Worker strncpy(p->id, str, sizeof(p->id) - 1);
116*de1e4e89SAndroid Build Coastguard Worker p->parse_peopt = pedit_parse_nopopt;
117*de1e4e89SAndroid Build Coastguard Worker goto reg;
118*de1e4e89SAndroid Build Coastguard Worker }
119*de1e4e89SAndroid Build Coastguard Worker return p;
120*de1e4e89SAndroid Build Coastguard Worker }
121*de1e4e89SAndroid Build Coastguard Worker
pack_key(struct m_pedit_sel * _sel,struct m_pedit_key * tkey)122*de1e4e89SAndroid Build Coastguard Worker int pack_key(struct m_pedit_sel *_sel, struct m_pedit_key *tkey)
123*de1e4e89SAndroid Build Coastguard Worker {
124*de1e4e89SAndroid Build Coastguard Worker struct tc_pedit_sel *sel = &_sel->sel;
125*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_key_ex *keys_ex = _sel->keys_ex;
126*de1e4e89SAndroid Build Coastguard Worker int hwm = sel->nkeys;
127*de1e4e89SAndroid Build Coastguard Worker
128*de1e4e89SAndroid Build Coastguard Worker if (hwm >= MAX_OFFS)
129*de1e4e89SAndroid Build Coastguard Worker return -1;
130*de1e4e89SAndroid Build Coastguard Worker
131*de1e4e89SAndroid Build Coastguard Worker if (tkey->off % 4) {
132*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "offsets MUST be in 32 bit boundaries\n");
133*de1e4e89SAndroid Build Coastguard Worker return -1;
134*de1e4e89SAndroid Build Coastguard Worker }
135*de1e4e89SAndroid Build Coastguard Worker
136*de1e4e89SAndroid Build Coastguard Worker sel->keys[hwm].val = tkey->val;
137*de1e4e89SAndroid Build Coastguard Worker sel->keys[hwm].mask = tkey->mask;
138*de1e4e89SAndroid Build Coastguard Worker sel->keys[hwm].off = tkey->off;
139*de1e4e89SAndroid Build Coastguard Worker sel->keys[hwm].at = tkey->at;
140*de1e4e89SAndroid Build Coastguard Worker sel->keys[hwm].offmask = tkey->offmask;
141*de1e4e89SAndroid Build Coastguard Worker sel->keys[hwm].shift = tkey->shift;
142*de1e4e89SAndroid Build Coastguard Worker
143*de1e4e89SAndroid Build Coastguard Worker if (_sel->extended) {
144*de1e4e89SAndroid Build Coastguard Worker keys_ex[hwm].htype = tkey->htype;
145*de1e4e89SAndroid Build Coastguard Worker keys_ex[hwm].cmd = tkey->cmd;
146*de1e4e89SAndroid Build Coastguard Worker } else {
147*de1e4e89SAndroid Build Coastguard Worker if (tkey->htype != TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK ||
148*de1e4e89SAndroid Build Coastguard Worker tkey->cmd != TCA_PEDIT_KEY_EX_CMD_SET) {
149*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
150*de1e4e89SAndroid Build Coastguard Worker "Munge parameters not supported. Use 'pedit ex munge ...'.\n");
151*de1e4e89SAndroid Build Coastguard Worker return -1;
152*de1e4e89SAndroid Build Coastguard Worker }
153*de1e4e89SAndroid Build Coastguard Worker }
154*de1e4e89SAndroid Build Coastguard Worker
155*de1e4e89SAndroid Build Coastguard Worker sel->nkeys++;
156*de1e4e89SAndroid Build Coastguard Worker return 0;
157*de1e4e89SAndroid Build Coastguard Worker }
158*de1e4e89SAndroid Build Coastguard Worker
pack_key32(__u32 retain,struct m_pedit_sel * sel,struct m_pedit_key * tkey)159*de1e4e89SAndroid Build Coastguard Worker int pack_key32(__u32 retain, struct m_pedit_sel *sel,
160*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_key *tkey)
161*de1e4e89SAndroid Build Coastguard Worker {
162*de1e4e89SAndroid Build Coastguard Worker if (tkey->off > (tkey->off & ~3)) {
163*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
164*de1e4e89SAndroid Build Coastguard Worker "pack_key32: 32 bit offsets must begin in 32bit boundaries\n");
165*de1e4e89SAndroid Build Coastguard Worker return -1;
166*de1e4e89SAndroid Build Coastguard Worker }
167*de1e4e89SAndroid Build Coastguard Worker
168*de1e4e89SAndroid Build Coastguard Worker tkey->val = htonl(tkey->val & retain);
169*de1e4e89SAndroid Build Coastguard Worker tkey->mask = htonl(tkey->mask | ~retain);
170*de1e4e89SAndroid Build Coastguard Worker return pack_key(sel, tkey);
171*de1e4e89SAndroid Build Coastguard Worker }
172*de1e4e89SAndroid Build Coastguard Worker
pack_key16(__u32 retain,struct m_pedit_sel * sel,struct m_pedit_key * tkey)173*de1e4e89SAndroid Build Coastguard Worker int pack_key16(__u32 retain, struct m_pedit_sel *sel,
174*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_key *tkey)
175*de1e4e89SAndroid Build Coastguard Worker {
176*de1e4e89SAndroid Build Coastguard Worker int ind, stride;
177*de1e4e89SAndroid Build Coastguard Worker __u32 m[4] = { 0x0000FFFF, 0xFF0000FF, 0xFFFF0000 };
178*de1e4e89SAndroid Build Coastguard Worker
179*de1e4e89SAndroid Build Coastguard Worker if (tkey->val > 0xFFFF || tkey->mask > 0xFFFF) {
180*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "pack_key16 bad value\n");
181*de1e4e89SAndroid Build Coastguard Worker return -1;
182*de1e4e89SAndroid Build Coastguard Worker }
183*de1e4e89SAndroid Build Coastguard Worker
184*de1e4e89SAndroid Build Coastguard Worker ind = tkey->off & 3;
185*de1e4e89SAndroid Build Coastguard Worker
186*de1e4e89SAndroid Build Coastguard Worker if (ind == 3) {
187*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "pack_key16 bad index value %d\n", ind);
188*de1e4e89SAndroid Build Coastguard Worker return -1;
189*de1e4e89SAndroid Build Coastguard Worker }
190*de1e4e89SAndroid Build Coastguard Worker
191*de1e4e89SAndroid Build Coastguard Worker stride = 8 * (2 - ind);
192*de1e4e89SAndroid Build Coastguard Worker tkey->val = htonl((tkey->val & retain) << stride);
193*de1e4e89SAndroid Build Coastguard Worker tkey->mask = htonl(((tkey->mask | ~retain) << stride) | m[ind]);
194*de1e4e89SAndroid Build Coastguard Worker
195*de1e4e89SAndroid Build Coastguard Worker tkey->off &= ~3;
196*de1e4e89SAndroid Build Coastguard Worker
197*de1e4e89SAndroid Build Coastguard Worker if (pedit_debug)
198*de1e4e89SAndroid Build Coastguard Worker printf("pack_key16: Final val %08x mask %08x\n",
199*de1e4e89SAndroid Build Coastguard Worker tkey->val, tkey->mask);
200*de1e4e89SAndroid Build Coastguard Worker return pack_key(sel, tkey);
201*de1e4e89SAndroid Build Coastguard Worker
202*de1e4e89SAndroid Build Coastguard Worker }
203*de1e4e89SAndroid Build Coastguard Worker
pack_key8(__u32 retain,struct m_pedit_sel * sel,struct m_pedit_key * tkey)204*de1e4e89SAndroid Build Coastguard Worker int pack_key8(__u32 retain, struct m_pedit_sel *sel, struct m_pedit_key *tkey)
205*de1e4e89SAndroid Build Coastguard Worker {
206*de1e4e89SAndroid Build Coastguard Worker int ind, stride;
207*de1e4e89SAndroid Build Coastguard Worker __u32 m[4] = { 0x00FFFFFF, 0xFF00FFFF, 0xFFFF00FF, 0xFFFFFF00 };
208*de1e4e89SAndroid Build Coastguard Worker
209*de1e4e89SAndroid Build Coastguard Worker if (tkey->val > 0xFF || tkey->mask > 0xFF) {
210*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "pack_key8 bad value (val %x mask %x\n",
211*de1e4e89SAndroid Build Coastguard Worker tkey->val, tkey->mask);
212*de1e4e89SAndroid Build Coastguard Worker return -1;
213*de1e4e89SAndroid Build Coastguard Worker }
214*de1e4e89SAndroid Build Coastguard Worker
215*de1e4e89SAndroid Build Coastguard Worker ind = tkey->off & 3;
216*de1e4e89SAndroid Build Coastguard Worker
217*de1e4e89SAndroid Build Coastguard Worker stride = 8 * (3 - ind);
218*de1e4e89SAndroid Build Coastguard Worker tkey->val = htonl((tkey->val & retain) << stride);
219*de1e4e89SAndroid Build Coastguard Worker tkey->mask = htonl(((tkey->mask | ~retain) << stride) | m[ind]);
220*de1e4e89SAndroid Build Coastguard Worker
221*de1e4e89SAndroid Build Coastguard Worker tkey->off &= ~3;
222*de1e4e89SAndroid Build Coastguard Worker
223*de1e4e89SAndroid Build Coastguard Worker if (pedit_debug)
224*de1e4e89SAndroid Build Coastguard Worker printf("pack_key8: Final word off %d val %08x mask %08x\n",
225*de1e4e89SAndroid Build Coastguard Worker tkey->off, tkey->val, tkey->mask);
226*de1e4e89SAndroid Build Coastguard Worker return pack_key(sel, tkey);
227*de1e4e89SAndroid Build Coastguard Worker }
228*de1e4e89SAndroid Build Coastguard Worker
pack_mac(struct m_pedit_sel * sel,struct m_pedit_key * tkey,__u8 * mac)229*de1e4e89SAndroid Build Coastguard Worker static int pack_mac(struct m_pedit_sel *sel, struct m_pedit_key *tkey,
230*de1e4e89SAndroid Build Coastguard Worker __u8 *mac)
231*de1e4e89SAndroid Build Coastguard Worker {
232*de1e4e89SAndroid Build Coastguard Worker int ret = 0;
233*de1e4e89SAndroid Build Coastguard Worker
234*de1e4e89SAndroid Build Coastguard Worker if (!(tkey->off & 0x3)) {
235*de1e4e89SAndroid Build Coastguard Worker tkey->mask = 0;
236*de1e4e89SAndroid Build Coastguard Worker tkey->val = ntohl(*((__u32 *)mac));
237*de1e4e89SAndroid Build Coastguard Worker ret |= pack_key32(~0, sel, tkey);
238*de1e4e89SAndroid Build Coastguard Worker
239*de1e4e89SAndroid Build Coastguard Worker tkey->off += 4;
240*de1e4e89SAndroid Build Coastguard Worker tkey->mask = 0;
241*de1e4e89SAndroid Build Coastguard Worker tkey->val = ntohs(*((__u16 *)&mac[4]));
242*de1e4e89SAndroid Build Coastguard Worker ret |= pack_key16(~0, sel, tkey);
243*de1e4e89SAndroid Build Coastguard Worker } else if (!(tkey->off & 0x1)) {
244*de1e4e89SAndroid Build Coastguard Worker tkey->mask = 0;
245*de1e4e89SAndroid Build Coastguard Worker tkey->val = ntohs(*((__u16 *)mac));
246*de1e4e89SAndroid Build Coastguard Worker ret |= pack_key16(~0, sel, tkey);
247*de1e4e89SAndroid Build Coastguard Worker
248*de1e4e89SAndroid Build Coastguard Worker tkey->off += 4;
249*de1e4e89SAndroid Build Coastguard Worker tkey->mask = 0;
250*de1e4e89SAndroid Build Coastguard Worker tkey->val = ntohl(*((__u32 *)(mac + 2)));
251*de1e4e89SAndroid Build Coastguard Worker ret |= pack_key32(~0, sel, tkey);
252*de1e4e89SAndroid Build Coastguard Worker } else {
253*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
254*de1e4e89SAndroid Build Coastguard Worker "pack_mac: mac offsets must begin in 32bit or 16bit boundaries\n");
255*de1e4e89SAndroid Build Coastguard Worker return -1;
256*de1e4e89SAndroid Build Coastguard Worker }
257*de1e4e89SAndroid Build Coastguard Worker
258*de1e4e89SAndroid Build Coastguard Worker return ret;
259*de1e4e89SAndroid Build Coastguard Worker }
260*de1e4e89SAndroid Build Coastguard Worker
pack_ipv6(struct m_pedit_sel * sel,struct m_pedit_key * tkey,__u32 * ipv6)261*de1e4e89SAndroid Build Coastguard Worker static int pack_ipv6(struct m_pedit_sel *sel, struct m_pedit_key *tkey,
262*de1e4e89SAndroid Build Coastguard Worker __u32 *ipv6)
263*de1e4e89SAndroid Build Coastguard Worker {
264*de1e4e89SAndroid Build Coastguard Worker int ret = 0;
265*de1e4e89SAndroid Build Coastguard Worker int i;
266*de1e4e89SAndroid Build Coastguard Worker
267*de1e4e89SAndroid Build Coastguard Worker if (tkey->off & 0x3) {
268*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
269*de1e4e89SAndroid Build Coastguard Worker "pack_ipv6: IPv6 offsets must begin in 32bit boundaries\n");
270*de1e4e89SAndroid Build Coastguard Worker return -1;
271*de1e4e89SAndroid Build Coastguard Worker }
272*de1e4e89SAndroid Build Coastguard Worker
273*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < 4; i++) {
274*de1e4e89SAndroid Build Coastguard Worker tkey->mask = 0;
275*de1e4e89SAndroid Build Coastguard Worker tkey->val = ntohl(ipv6[i]);
276*de1e4e89SAndroid Build Coastguard Worker
277*de1e4e89SAndroid Build Coastguard Worker ret = pack_key32(~0, sel, tkey);
278*de1e4e89SAndroid Build Coastguard Worker if (ret)
279*de1e4e89SAndroid Build Coastguard Worker return ret;
280*de1e4e89SAndroid Build Coastguard Worker
281*de1e4e89SAndroid Build Coastguard Worker tkey->off += 4;
282*de1e4e89SAndroid Build Coastguard Worker }
283*de1e4e89SAndroid Build Coastguard Worker
284*de1e4e89SAndroid Build Coastguard Worker return 0;
285*de1e4e89SAndroid Build Coastguard Worker }
286*de1e4e89SAndroid Build Coastguard Worker
parse_val(int * argc_p,char *** argv_p,__u32 * val,int type)287*de1e4e89SAndroid Build Coastguard Worker int parse_val(int *argc_p, char ***argv_p, __u32 *val, int type)
288*de1e4e89SAndroid Build Coastguard Worker {
289*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
290*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
291*de1e4e89SAndroid Build Coastguard Worker
292*de1e4e89SAndroid Build Coastguard Worker if (argc <= 0)
293*de1e4e89SAndroid Build Coastguard Worker return -1;
294*de1e4e89SAndroid Build Coastguard Worker
295*de1e4e89SAndroid Build Coastguard Worker if (type == TINT)
296*de1e4e89SAndroid Build Coastguard Worker return get_integer((int *)val, *argv, 0);
297*de1e4e89SAndroid Build Coastguard Worker
298*de1e4e89SAndroid Build Coastguard Worker if (type == TU32)
299*de1e4e89SAndroid Build Coastguard Worker return get_u32(val, *argv, 0);
300*de1e4e89SAndroid Build Coastguard Worker
301*de1e4e89SAndroid Build Coastguard Worker if (type == TIPV4) {
302*de1e4e89SAndroid Build Coastguard Worker inet_prefix addr;
303*de1e4e89SAndroid Build Coastguard Worker
304*de1e4e89SAndroid Build Coastguard Worker if (get_prefix_1(&addr, *argv, AF_INET))
305*de1e4e89SAndroid Build Coastguard Worker return -1;
306*de1e4e89SAndroid Build Coastguard Worker
307*de1e4e89SAndroid Build Coastguard Worker *val = addr.data[0];
308*de1e4e89SAndroid Build Coastguard Worker return 0;
309*de1e4e89SAndroid Build Coastguard Worker }
310*de1e4e89SAndroid Build Coastguard Worker
311*de1e4e89SAndroid Build Coastguard Worker if (type == TIPV6) {
312*de1e4e89SAndroid Build Coastguard Worker inet_prefix addr;
313*de1e4e89SAndroid Build Coastguard Worker
314*de1e4e89SAndroid Build Coastguard Worker if (get_prefix_1(&addr, *argv, AF_INET6))
315*de1e4e89SAndroid Build Coastguard Worker return -1;
316*de1e4e89SAndroid Build Coastguard Worker
317*de1e4e89SAndroid Build Coastguard Worker memcpy(val, addr.data, addr.bytelen);
318*de1e4e89SAndroid Build Coastguard Worker
319*de1e4e89SAndroid Build Coastguard Worker return 0;
320*de1e4e89SAndroid Build Coastguard Worker }
321*de1e4e89SAndroid Build Coastguard Worker
322*de1e4e89SAndroid Build Coastguard Worker if (type == TMAC) {
323*de1e4e89SAndroid Build Coastguard Worker #define MAC_ALEN 6
324*de1e4e89SAndroid Build Coastguard Worker int ret = ll_addr_a2n((char *)val, MAC_ALEN, *argv);
325*de1e4e89SAndroid Build Coastguard Worker
326*de1e4e89SAndroid Build Coastguard Worker if (ret == MAC_ALEN)
327*de1e4e89SAndroid Build Coastguard Worker return 0;
328*de1e4e89SAndroid Build Coastguard Worker }
329*de1e4e89SAndroid Build Coastguard Worker
330*de1e4e89SAndroid Build Coastguard Worker return -1;
331*de1e4e89SAndroid Build Coastguard Worker }
332*de1e4e89SAndroid Build Coastguard Worker
parse_cmd(int * argc_p,char *** argv_p,__u32 len,int type,__u32 retain,struct m_pedit_sel * sel,struct m_pedit_key * tkey)333*de1e4e89SAndroid Build Coastguard Worker int parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type, __u32 retain,
334*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_sel *sel, struct m_pedit_key *tkey)
335*de1e4e89SAndroid Build Coastguard Worker {
336*de1e4e89SAndroid Build Coastguard Worker __u32 mask[4] = { 0 };
337*de1e4e89SAndroid Build Coastguard Worker __u32 val[4] = { 0 };
338*de1e4e89SAndroid Build Coastguard Worker __u32 *m = &mask[0];
339*de1e4e89SAndroid Build Coastguard Worker __u32 *v = &val[0];
340*de1e4e89SAndroid Build Coastguard Worker __u32 o = 0xFF;
341*de1e4e89SAndroid Build Coastguard Worker int res = -1;
342*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
343*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
344*de1e4e89SAndroid Build Coastguard Worker
345*de1e4e89SAndroid Build Coastguard Worker if (argc <= 0)
346*de1e4e89SAndroid Build Coastguard Worker return -1;
347*de1e4e89SAndroid Build Coastguard Worker
348*de1e4e89SAndroid Build Coastguard Worker if (pedit_debug)
349*de1e4e89SAndroid Build Coastguard Worker printf("parse_cmd argc %d %s offset %d length %d\n",
350*de1e4e89SAndroid Build Coastguard Worker argc, *argv, tkey->off, len);
351*de1e4e89SAndroid Build Coastguard Worker
352*de1e4e89SAndroid Build Coastguard Worker if (len == 2)
353*de1e4e89SAndroid Build Coastguard Worker o = 0xFFFF;
354*de1e4e89SAndroid Build Coastguard Worker if (len == 4)
355*de1e4e89SAndroid Build Coastguard Worker o = 0xFFFFFFFF;
356*de1e4e89SAndroid Build Coastguard Worker
357*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "invert") == 0) {
358*de1e4e89SAndroid Build Coastguard Worker *v = *m = o;
359*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "set") == 0 ||
360*de1e4e89SAndroid Build Coastguard Worker matches(*argv, "add") == 0) {
361*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "add") == 0)
362*de1e4e89SAndroid Build Coastguard Worker tkey->cmd = TCA_PEDIT_KEY_EX_CMD_ADD;
363*de1e4e89SAndroid Build Coastguard Worker
364*de1e4e89SAndroid Build Coastguard Worker if (!sel->extended && tkey->cmd) {
365*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
366*de1e4e89SAndroid Build Coastguard Worker "Non extended mode. only 'set' command is supported\n");
367*de1e4e89SAndroid Build Coastguard Worker return -1;
368*de1e4e89SAndroid Build Coastguard Worker }
369*de1e4e89SAndroid Build Coastguard Worker
370*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
371*de1e4e89SAndroid Build Coastguard Worker if (parse_val(&argc, &argv, val, type))
372*de1e4e89SAndroid Build Coastguard Worker return -1;
373*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "preserve") == 0) {
374*de1e4e89SAndroid Build Coastguard Worker retain = 0;
375*de1e4e89SAndroid Build Coastguard Worker } else {
376*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "clear") != 0)
377*de1e4e89SAndroid Build Coastguard Worker return -1;
378*de1e4e89SAndroid Build Coastguard Worker }
379*de1e4e89SAndroid Build Coastguard Worker
380*de1e4e89SAndroid Build Coastguard Worker argc--;
381*de1e4e89SAndroid Build Coastguard Worker argv++;
382*de1e4e89SAndroid Build Coastguard Worker
383*de1e4e89SAndroid Build Coastguard Worker if (argc && matches(*argv, "retain") == 0) {
384*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
385*de1e4e89SAndroid Build Coastguard Worker if (parse_val(&argc, &argv, &retain, TU32))
386*de1e4e89SAndroid Build Coastguard Worker return -1;
387*de1e4e89SAndroid Build Coastguard Worker argc--;
388*de1e4e89SAndroid Build Coastguard Worker argv++;
389*de1e4e89SAndroid Build Coastguard Worker }
390*de1e4e89SAndroid Build Coastguard Worker
391*de1e4e89SAndroid Build Coastguard Worker if (len > 4 && retain != ~0) {
392*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
393*de1e4e89SAndroid Build Coastguard Worker "retain is not supported for fields longer the 32 bits\n");
394*de1e4e89SAndroid Build Coastguard Worker return -1;
395*de1e4e89SAndroid Build Coastguard Worker }
396*de1e4e89SAndroid Build Coastguard Worker
397*de1e4e89SAndroid Build Coastguard Worker if (type == TMAC) {
398*de1e4e89SAndroid Build Coastguard Worker res = pack_mac(sel, tkey, (__u8 *)val);
399*de1e4e89SAndroid Build Coastguard Worker goto done;
400*de1e4e89SAndroid Build Coastguard Worker }
401*de1e4e89SAndroid Build Coastguard Worker
402*de1e4e89SAndroid Build Coastguard Worker if (type == TIPV6) {
403*de1e4e89SAndroid Build Coastguard Worker res = pack_ipv6(sel, tkey, val);
404*de1e4e89SAndroid Build Coastguard Worker goto done;
405*de1e4e89SAndroid Build Coastguard Worker }
406*de1e4e89SAndroid Build Coastguard Worker
407*de1e4e89SAndroid Build Coastguard Worker tkey->val = *v;
408*de1e4e89SAndroid Build Coastguard Worker tkey->mask = *m;
409*de1e4e89SAndroid Build Coastguard Worker
410*de1e4e89SAndroid Build Coastguard Worker if (type == TIPV4)
411*de1e4e89SAndroid Build Coastguard Worker tkey->val = ntohl(tkey->val);
412*de1e4e89SAndroid Build Coastguard Worker
413*de1e4e89SAndroid Build Coastguard Worker if (len == 1) {
414*de1e4e89SAndroid Build Coastguard Worker res = pack_key8(retain, sel, tkey);
415*de1e4e89SAndroid Build Coastguard Worker goto done;
416*de1e4e89SAndroid Build Coastguard Worker }
417*de1e4e89SAndroid Build Coastguard Worker if (len == 2) {
418*de1e4e89SAndroid Build Coastguard Worker res = pack_key16(retain, sel, tkey);
419*de1e4e89SAndroid Build Coastguard Worker goto done;
420*de1e4e89SAndroid Build Coastguard Worker }
421*de1e4e89SAndroid Build Coastguard Worker if (len == 4) {
422*de1e4e89SAndroid Build Coastguard Worker res = pack_key32(retain, sel, tkey);
423*de1e4e89SAndroid Build Coastguard Worker goto done;
424*de1e4e89SAndroid Build Coastguard Worker }
425*de1e4e89SAndroid Build Coastguard Worker
426*de1e4e89SAndroid Build Coastguard Worker return -1;
427*de1e4e89SAndroid Build Coastguard Worker done:
428*de1e4e89SAndroid Build Coastguard Worker if (pedit_debug)
429*de1e4e89SAndroid Build Coastguard Worker printf("parse_cmd done argc %d %s offset %d length %d\n",
430*de1e4e89SAndroid Build Coastguard Worker argc, *argv, tkey->off, len);
431*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
432*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
433*de1e4e89SAndroid Build Coastguard Worker return res;
434*de1e4e89SAndroid Build Coastguard Worker
435*de1e4e89SAndroid Build Coastguard Worker }
436*de1e4e89SAndroid Build Coastguard Worker
parse_offset(int * argc_p,char *** argv_p,struct m_pedit_sel * sel,struct m_pedit_key * tkey)437*de1e4e89SAndroid Build Coastguard Worker int parse_offset(int *argc_p, char ***argv_p, struct m_pedit_sel *sel,
438*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_key *tkey)
439*de1e4e89SAndroid Build Coastguard Worker {
440*de1e4e89SAndroid Build Coastguard Worker int off;
441*de1e4e89SAndroid Build Coastguard Worker __u32 len, retain;
442*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
443*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
444*de1e4e89SAndroid Build Coastguard Worker int res = -1;
445*de1e4e89SAndroid Build Coastguard Worker
446*de1e4e89SAndroid Build Coastguard Worker if (argc <= 0)
447*de1e4e89SAndroid Build Coastguard Worker return -1;
448*de1e4e89SAndroid Build Coastguard Worker
449*de1e4e89SAndroid Build Coastguard Worker if (get_integer(&off, *argv, 0))
450*de1e4e89SAndroid Build Coastguard Worker return -1;
451*de1e4e89SAndroid Build Coastguard Worker tkey->off = off;
452*de1e4e89SAndroid Build Coastguard Worker
453*de1e4e89SAndroid Build Coastguard Worker argc--;
454*de1e4e89SAndroid Build Coastguard Worker argv++;
455*de1e4e89SAndroid Build Coastguard Worker
456*de1e4e89SAndroid Build Coastguard Worker if (argc <= 0)
457*de1e4e89SAndroid Build Coastguard Worker return -1;
458*de1e4e89SAndroid Build Coastguard Worker
459*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "u32") == 0) {
460*de1e4e89SAndroid Build Coastguard Worker len = 4;
461*de1e4e89SAndroid Build Coastguard Worker retain = 0xFFFFFFFF;
462*de1e4e89SAndroid Build Coastguard Worker goto done;
463*de1e4e89SAndroid Build Coastguard Worker }
464*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "u16") == 0) {
465*de1e4e89SAndroid Build Coastguard Worker len = 2;
466*de1e4e89SAndroid Build Coastguard Worker retain = 0xffff;
467*de1e4e89SAndroid Build Coastguard Worker goto done;
468*de1e4e89SAndroid Build Coastguard Worker }
469*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "u8") == 0) {
470*de1e4e89SAndroid Build Coastguard Worker len = 1;
471*de1e4e89SAndroid Build Coastguard Worker retain = 0xff;
472*de1e4e89SAndroid Build Coastguard Worker goto done;
473*de1e4e89SAndroid Build Coastguard Worker }
474*de1e4e89SAndroid Build Coastguard Worker
475*de1e4e89SAndroid Build Coastguard Worker return -1;
476*de1e4e89SAndroid Build Coastguard Worker
477*de1e4e89SAndroid Build Coastguard Worker done:
478*de1e4e89SAndroid Build Coastguard Worker
479*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
480*de1e4e89SAndroid Build Coastguard Worker
481*de1e4e89SAndroid Build Coastguard Worker /* [at <someval> offmask <maskval> shift <shiftval>] */
482*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "at") == 0) {
483*de1e4e89SAndroid Build Coastguard Worker
484*de1e4e89SAndroid Build Coastguard Worker __u32 atv = 0, offmask = 0x0, shift = 0;
485*de1e4e89SAndroid Build Coastguard Worker
486*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
487*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&atv, *argv, 0))
488*de1e4e89SAndroid Build Coastguard Worker return -1;
489*de1e4e89SAndroid Build Coastguard Worker tkey->at = atv;
490*de1e4e89SAndroid Build Coastguard Worker
491*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
492*de1e4e89SAndroid Build Coastguard Worker
493*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&offmask, *argv, 16))
494*de1e4e89SAndroid Build Coastguard Worker return -1;
495*de1e4e89SAndroid Build Coastguard Worker tkey->offmask = offmask;
496*de1e4e89SAndroid Build Coastguard Worker
497*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
498*de1e4e89SAndroid Build Coastguard Worker
499*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&shift, *argv, 0))
500*de1e4e89SAndroid Build Coastguard Worker return -1;
501*de1e4e89SAndroid Build Coastguard Worker tkey->shift = shift;
502*de1e4e89SAndroid Build Coastguard Worker
503*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
504*de1e4e89SAndroid Build Coastguard Worker }
505*de1e4e89SAndroid Build Coastguard Worker
506*de1e4e89SAndroid Build Coastguard Worker res = parse_cmd(&argc, &argv, len, TU32, retain, sel, tkey);
507*de1e4e89SAndroid Build Coastguard Worker
508*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
509*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
510*de1e4e89SAndroid Build Coastguard Worker return res;
511*de1e4e89SAndroid Build Coastguard Worker }
512*de1e4e89SAndroid Build Coastguard Worker
parse_munge(int * argc_p,char *** argv_p,struct m_pedit_sel * sel)513*de1e4e89SAndroid Build Coastguard Worker static int parse_munge(int *argc_p, char ***argv_p, struct m_pedit_sel *sel)
514*de1e4e89SAndroid Build Coastguard Worker {
515*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_key tkey = {};
516*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
517*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
518*de1e4e89SAndroid Build Coastguard Worker int res = -1;
519*de1e4e89SAndroid Build Coastguard Worker
520*de1e4e89SAndroid Build Coastguard Worker if (argc <= 0)
521*de1e4e89SAndroid Build Coastguard Worker return -1;
522*de1e4e89SAndroid Build Coastguard Worker
523*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "offset") == 0) {
524*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
525*de1e4e89SAndroid Build Coastguard Worker res = parse_offset(&argc, &argv, sel, &tkey);
526*de1e4e89SAndroid Build Coastguard Worker goto done;
527*de1e4e89SAndroid Build Coastguard Worker } else {
528*de1e4e89SAndroid Build Coastguard Worker char k[16];
529*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_util *p = NULL;
530*de1e4e89SAndroid Build Coastguard Worker
531*de1e4e89SAndroid Build Coastguard Worker strncpy(k, *argv, sizeof(k) - 1);
532*de1e4e89SAndroid Build Coastguard Worker
533*de1e4e89SAndroid Build Coastguard Worker if (argc > 0) {
534*de1e4e89SAndroid Build Coastguard Worker p = get_pedit_kind(k);
535*de1e4e89SAndroid Build Coastguard Worker if (p == NULL)
536*de1e4e89SAndroid Build Coastguard Worker goto bad_val;
537*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
538*de1e4e89SAndroid Build Coastguard Worker res = p->parse_peopt(&argc, &argv, sel, &tkey);
539*de1e4e89SAndroid Build Coastguard Worker if (res < 0) {
540*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "bad pedit parsing\n");
541*de1e4e89SAndroid Build Coastguard Worker goto bad_val;
542*de1e4e89SAndroid Build Coastguard Worker }
543*de1e4e89SAndroid Build Coastguard Worker goto done;
544*de1e4e89SAndroid Build Coastguard Worker }
545*de1e4e89SAndroid Build Coastguard Worker }
546*de1e4e89SAndroid Build Coastguard Worker
547*de1e4e89SAndroid Build Coastguard Worker bad_val:
548*de1e4e89SAndroid Build Coastguard Worker return -1;
549*de1e4e89SAndroid Build Coastguard Worker
550*de1e4e89SAndroid Build Coastguard Worker done:
551*de1e4e89SAndroid Build Coastguard Worker
552*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
553*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
554*de1e4e89SAndroid Build Coastguard Worker return res;
555*de1e4e89SAndroid Build Coastguard Worker }
556*de1e4e89SAndroid Build Coastguard Worker
pedit_keys_ex_getattr(struct rtattr * attr,struct m_pedit_key_ex * keys_ex,int n)557*de1e4e89SAndroid Build Coastguard Worker static int pedit_keys_ex_getattr(struct rtattr *attr,
558*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_key_ex *keys_ex, int n)
559*de1e4e89SAndroid Build Coastguard Worker {
560*de1e4e89SAndroid Build Coastguard Worker struct rtattr *i;
561*de1e4e89SAndroid Build Coastguard Worker int rem = RTA_PAYLOAD(attr);
562*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tb[TCA_PEDIT_KEY_EX_MAX + 1];
563*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_key_ex *k = keys_ex;
564*de1e4e89SAndroid Build Coastguard Worker
565*de1e4e89SAndroid Build Coastguard Worker for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
566*de1e4e89SAndroid Build Coastguard Worker if (!n)
567*de1e4e89SAndroid Build Coastguard Worker return -1;
568*de1e4e89SAndroid Build Coastguard Worker
569*de1e4e89SAndroid Build Coastguard Worker if (i->rta_type != TCA_PEDIT_KEY_EX)
570*de1e4e89SAndroid Build Coastguard Worker return -1;
571*de1e4e89SAndroid Build Coastguard Worker
572*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(tb, TCA_PEDIT_KEY_EX_MAX, i);
573*de1e4e89SAndroid Build Coastguard Worker
574*de1e4e89SAndroid Build Coastguard Worker k->htype = rta_getattr_u16(tb[TCA_PEDIT_KEY_EX_HTYPE]);
575*de1e4e89SAndroid Build Coastguard Worker k->cmd = rta_getattr_u16(tb[TCA_PEDIT_KEY_EX_CMD]);
576*de1e4e89SAndroid Build Coastguard Worker
577*de1e4e89SAndroid Build Coastguard Worker k++;
578*de1e4e89SAndroid Build Coastguard Worker n--;
579*de1e4e89SAndroid Build Coastguard Worker }
580*de1e4e89SAndroid Build Coastguard Worker
581*de1e4e89SAndroid Build Coastguard Worker return !!n;
582*de1e4e89SAndroid Build Coastguard Worker }
583*de1e4e89SAndroid Build Coastguard Worker
pedit_keys_ex_addattr(struct m_pedit_sel * sel,struct nlmsghdr * n)584*de1e4e89SAndroid Build Coastguard Worker static int pedit_keys_ex_addattr(struct m_pedit_sel *sel, struct nlmsghdr *n)
585*de1e4e89SAndroid Build Coastguard Worker {
586*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_key_ex *k = sel->keys_ex;
587*de1e4e89SAndroid Build Coastguard Worker struct rtattr *keys_start;
588*de1e4e89SAndroid Build Coastguard Worker int i;
589*de1e4e89SAndroid Build Coastguard Worker
590*de1e4e89SAndroid Build Coastguard Worker if (!sel->extended)
591*de1e4e89SAndroid Build Coastguard Worker return 0;
592*de1e4e89SAndroid Build Coastguard Worker
593*de1e4e89SAndroid Build Coastguard Worker keys_start = addattr_nest(n, MAX_MSG, TCA_PEDIT_KEYS_EX | NLA_F_NESTED);
594*de1e4e89SAndroid Build Coastguard Worker
595*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < sel->sel.nkeys; i++) {
596*de1e4e89SAndroid Build Coastguard Worker struct rtattr *key_start;
597*de1e4e89SAndroid Build Coastguard Worker
598*de1e4e89SAndroid Build Coastguard Worker key_start = addattr_nest(n, MAX_MSG,
599*de1e4e89SAndroid Build Coastguard Worker TCA_PEDIT_KEY_EX | NLA_F_NESTED);
600*de1e4e89SAndroid Build Coastguard Worker
601*de1e4e89SAndroid Build Coastguard Worker if (addattr16(n, MAX_MSG, TCA_PEDIT_KEY_EX_HTYPE, k->htype) ||
602*de1e4e89SAndroid Build Coastguard Worker addattr16(n, MAX_MSG, TCA_PEDIT_KEY_EX_CMD, k->cmd)) {
603*de1e4e89SAndroid Build Coastguard Worker return -1;
604*de1e4e89SAndroid Build Coastguard Worker }
605*de1e4e89SAndroid Build Coastguard Worker
606*de1e4e89SAndroid Build Coastguard Worker addattr_nest_end(n, key_start);
607*de1e4e89SAndroid Build Coastguard Worker
608*de1e4e89SAndroid Build Coastguard Worker k++;
609*de1e4e89SAndroid Build Coastguard Worker }
610*de1e4e89SAndroid Build Coastguard Worker
611*de1e4e89SAndroid Build Coastguard Worker addattr_nest_end(n, keys_start);
612*de1e4e89SAndroid Build Coastguard Worker
613*de1e4e89SAndroid Build Coastguard Worker return 0;
614*de1e4e89SAndroid Build Coastguard Worker }
615*de1e4e89SAndroid Build Coastguard Worker
parse_pedit(struct action_util * a,int * argc_p,char *** argv_p,int tca_id,struct nlmsghdr * n)616*de1e4e89SAndroid Build Coastguard Worker int parse_pedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
617*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr *n)
618*de1e4e89SAndroid Build Coastguard Worker {
619*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_sel sel = {};
620*de1e4e89SAndroid Build Coastguard Worker
621*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
622*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
623*de1e4e89SAndroid Build Coastguard Worker int ok = 0, iok = 0;
624*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tail;
625*de1e4e89SAndroid Build Coastguard Worker
626*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
627*de1e4e89SAndroid Build Coastguard Worker if (pedit_debug > 1)
628*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "while pedit (%d:%s)\n", argc, *argv);
629*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "pedit") == 0) {
630*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
631*de1e4e89SAndroid Build Coastguard Worker ok++;
632*de1e4e89SAndroid Build Coastguard Worker
633*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "ex") == 0) {
634*de1e4e89SAndroid Build Coastguard Worker if (ok > 1) {
635*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
636*de1e4e89SAndroid Build Coastguard Worker "'ex' must be before first 'munge'\n");
637*de1e4e89SAndroid Build Coastguard Worker explain();
638*de1e4e89SAndroid Build Coastguard Worker return -1;
639*de1e4e89SAndroid Build Coastguard Worker }
640*de1e4e89SAndroid Build Coastguard Worker sel.extended = true;
641*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
642*de1e4e89SAndroid Build Coastguard Worker }
643*de1e4e89SAndroid Build Coastguard Worker
644*de1e4e89SAndroid Build Coastguard Worker continue;
645*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "help") == 0) {
646*de1e4e89SAndroid Build Coastguard Worker usage();
647*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "munge") == 0) {
648*de1e4e89SAndroid Build Coastguard Worker if (!ok) {
649*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Bad pedit construct (%s)\n",
650*de1e4e89SAndroid Build Coastguard Worker *argv);
651*de1e4e89SAndroid Build Coastguard Worker explain();
652*de1e4e89SAndroid Build Coastguard Worker return -1;
653*de1e4e89SAndroid Build Coastguard Worker }
654*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
655*de1e4e89SAndroid Build Coastguard Worker
656*de1e4e89SAndroid Build Coastguard Worker if (parse_munge(&argc, &argv, &sel)) {
657*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Bad pedit construct (%s)\n",
658*de1e4e89SAndroid Build Coastguard Worker *argv);
659*de1e4e89SAndroid Build Coastguard Worker explain();
660*de1e4e89SAndroid Build Coastguard Worker return -1;
661*de1e4e89SAndroid Build Coastguard Worker }
662*de1e4e89SAndroid Build Coastguard Worker ok++;
663*de1e4e89SAndroid Build Coastguard Worker } else {
664*de1e4e89SAndroid Build Coastguard Worker break;
665*de1e4e89SAndroid Build Coastguard Worker }
666*de1e4e89SAndroid Build Coastguard Worker
667*de1e4e89SAndroid Build Coastguard Worker }
668*de1e4e89SAndroid Build Coastguard Worker
669*de1e4e89SAndroid Build Coastguard Worker if (!ok) {
670*de1e4e89SAndroid Build Coastguard Worker explain();
671*de1e4e89SAndroid Build Coastguard Worker return -1;
672*de1e4e89SAndroid Build Coastguard Worker }
673*de1e4e89SAndroid Build Coastguard Worker
674*de1e4e89SAndroid Build Coastguard Worker parse_action_control_dflt(&argc, &argv, &sel.sel.action, false, TC_ACT_OK);
675*de1e4e89SAndroid Build Coastguard Worker
676*de1e4e89SAndroid Build Coastguard Worker if (argc) {
677*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "index") == 0) {
678*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
679*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&sel.sel.index, *argv, 10)) {
680*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Pedit: Illegal \"index\"\n");
681*de1e4e89SAndroid Build Coastguard Worker return -1;
682*de1e4e89SAndroid Build Coastguard Worker }
683*de1e4e89SAndroid Build Coastguard Worker argc--;
684*de1e4e89SAndroid Build Coastguard Worker argv++;
685*de1e4e89SAndroid Build Coastguard Worker iok++;
686*de1e4e89SAndroid Build Coastguard Worker }
687*de1e4e89SAndroid Build Coastguard Worker }
688*de1e4e89SAndroid Build Coastguard Worker
689*de1e4e89SAndroid Build Coastguard Worker tail = NLMSG_TAIL(n);
690*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, tca_id, NULL, 0);
691*de1e4e89SAndroid Build Coastguard Worker if (!sel.extended) {
692*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_PEDIT_PARMS, &sel,
693*de1e4e89SAndroid Build Coastguard Worker sizeof(sel.sel) +
694*de1e4e89SAndroid Build Coastguard Worker sel.sel.nkeys * sizeof(struct tc_pedit_key));
695*de1e4e89SAndroid Build Coastguard Worker } else {
696*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_PEDIT_PARMS_EX, &sel,
697*de1e4e89SAndroid Build Coastguard Worker sizeof(sel.sel) +
698*de1e4e89SAndroid Build Coastguard Worker sel.sel.nkeys * sizeof(struct tc_pedit_key));
699*de1e4e89SAndroid Build Coastguard Worker
700*de1e4e89SAndroid Build Coastguard Worker pedit_keys_ex_addattr(&sel, n);
701*de1e4e89SAndroid Build Coastguard Worker }
702*de1e4e89SAndroid Build Coastguard Worker
703*de1e4e89SAndroid Build Coastguard Worker tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail;
704*de1e4e89SAndroid Build Coastguard Worker
705*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
706*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
707*de1e4e89SAndroid Build Coastguard Worker return 0;
708*de1e4e89SAndroid Build Coastguard Worker }
709*de1e4e89SAndroid Build Coastguard Worker
710*de1e4e89SAndroid Build Coastguard Worker const char *pedit_htype_str[] = {
711*de1e4e89SAndroid Build Coastguard Worker [TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK] = "",
712*de1e4e89SAndroid Build Coastguard Worker [TCA_PEDIT_KEY_EX_HDR_TYPE_ETH] = "eth",
713*de1e4e89SAndroid Build Coastguard Worker [TCA_PEDIT_KEY_EX_HDR_TYPE_IP4] = "ipv4",
714*de1e4e89SAndroid Build Coastguard Worker [TCA_PEDIT_KEY_EX_HDR_TYPE_IP6] = "ipv6",
715*de1e4e89SAndroid Build Coastguard Worker [TCA_PEDIT_KEY_EX_HDR_TYPE_TCP] = "tcp",
716*de1e4e89SAndroid Build Coastguard Worker [TCA_PEDIT_KEY_EX_HDR_TYPE_UDP] = "udp",
717*de1e4e89SAndroid Build Coastguard Worker };
718*de1e4e89SAndroid Build Coastguard Worker
print_pedit_location(FILE * f,enum pedit_header_type htype,__u32 off)719*de1e4e89SAndroid Build Coastguard Worker static void print_pedit_location(FILE *f,
720*de1e4e89SAndroid Build Coastguard Worker enum pedit_header_type htype, __u32 off)
721*de1e4e89SAndroid Build Coastguard Worker {
722*de1e4e89SAndroid Build Coastguard Worker if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK) {
723*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "%d", (unsigned int)off);
724*de1e4e89SAndroid Build Coastguard Worker return;
725*de1e4e89SAndroid Build Coastguard Worker }
726*de1e4e89SAndroid Build Coastguard Worker
727*de1e4e89SAndroid Build Coastguard Worker if (htype < ARRAY_SIZE(pedit_htype_str))
728*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "%s", pedit_htype_str[htype]);
729*de1e4e89SAndroid Build Coastguard Worker else
730*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "unknown(%d)", htype);
731*de1e4e89SAndroid Build Coastguard Worker
732*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "%c%d", (int)off >= 0 ? '+' : '-', abs((int)off));
733*de1e4e89SAndroid Build Coastguard Worker }
734*de1e4e89SAndroid Build Coastguard Worker
print_pedit(struct action_util * au,FILE * f,struct rtattr * arg)735*de1e4e89SAndroid Build Coastguard Worker int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg)
736*de1e4e89SAndroid Build Coastguard Worker {
737*de1e4e89SAndroid Build Coastguard Worker struct tc_pedit_sel *sel;
738*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tb[TCA_PEDIT_MAX + 1];
739*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_key_ex *keys_ex = NULL;
740*de1e4e89SAndroid Build Coastguard Worker
741*de1e4e89SAndroid Build Coastguard Worker if (arg == NULL)
742*de1e4e89SAndroid Build Coastguard Worker return -1;
743*de1e4e89SAndroid Build Coastguard Worker
744*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(tb, TCA_PEDIT_MAX, arg);
745*de1e4e89SAndroid Build Coastguard Worker
746*de1e4e89SAndroid Build Coastguard Worker if (!tb[TCA_PEDIT_PARMS] && !tb[TCA_PEDIT_PARMS_EX]) {
747*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "[NULL pedit parameters]");
748*de1e4e89SAndroid Build Coastguard Worker return -1;
749*de1e4e89SAndroid Build Coastguard Worker }
750*de1e4e89SAndroid Build Coastguard Worker
751*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_PEDIT_PARMS]) {
752*de1e4e89SAndroid Build Coastguard Worker sel = RTA_DATA(tb[TCA_PEDIT_PARMS]);
753*de1e4e89SAndroid Build Coastguard Worker } else {
754*de1e4e89SAndroid Build Coastguard Worker int err;
755*de1e4e89SAndroid Build Coastguard Worker
756*de1e4e89SAndroid Build Coastguard Worker sel = RTA_DATA(tb[TCA_PEDIT_PARMS_EX]);
757*de1e4e89SAndroid Build Coastguard Worker
758*de1e4e89SAndroid Build Coastguard Worker if (!tb[TCA_PEDIT_KEYS_EX]) {
759*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "Netlink error\n");
760*de1e4e89SAndroid Build Coastguard Worker return -1;
761*de1e4e89SAndroid Build Coastguard Worker }
762*de1e4e89SAndroid Build Coastguard Worker
763*de1e4e89SAndroid Build Coastguard Worker keys_ex = calloc(sel->nkeys, sizeof(*keys_ex));
764*de1e4e89SAndroid Build Coastguard Worker if (!keys_ex) {
765*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "Out of memory\n");
766*de1e4e89SAndroid Build Coastguard Worker return -1;
767*de1e4e89SAndroid Build Coastguard Worker }
768*de1e4e89SAndroid Build Coastguard Worker
769*de1e4e89SAndroid Build Coastguard Worker err = pedit_keys_ex_getattr(tb[TCA_PEDIT_KEYS_EX], keys_ex,
770*de1e4e89SAndroid Build Coastguard Worker sel->nkeys);
771*de1e4e89SAndroid Build Coastguard Worker if (err) {
772*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "Netlink error\n");
773*de1e4e89SAndroid Build Coastguard Worker
774*de1e4e89SAndroid Build Coastguard Worker free(keys_ex);
775*de1e4e89SAndroid Build Coastguard Worker return -1;
776*de1e4e89SAndroid Build Coastguard Worker }
777*de1e4e89SAndroid Build Coastguard Worker }
778*de1e4e89SAndroid Build Coastguard Worker
779*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " pedit ");
780*de1e4e89SAndroid Build Coastguard Worker print_action_control(f, "action ", sel->action, " ");
781*de1e4e89SAndroid Build Coastguard Worker fprintf(f,"keys %d\n ", sel->nkeys);
782*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\t index %u ref %d bind %d", sel->index, sel->refcnt,
783*de1e4e89SAndroid Build Coastguard Worker sel->bindcnt);
784*de1e4e89SAndroid Build Coastguard Worker
785*de1e4e89SAndroid Build Coastguard Worker if (show_stats) {
786*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_PEDIT_TM]) {
787*de1e4e89SAndroid Build Coastguard Worker struct tcf_t *tm = RTA_DATA(tb[TCA_PEDIT_TM]);
788*de1e4e89SAndroid Build Coastguard Worker
789*de1e4e89SAndroid Build Coastguard Worker print_tm(f, tm);
790*de1e4e89SAndroid Build Coastguard Worker }
791*de1e4e89SAndroid Build Coastguard Worker }
792*de1e4e89SAndroid Build Coastguard Worker if (sel->nkeys) {
793*de1e4e89SAndroid Build Coastguard Worker int i;
794*de1e4e89SAndroid Build Coastguard Worker struct tc_pedit_key *key = sel->keys;
795*de1e4e89SAndroid Build Coastguard Worker struct m_pedit_key_ex *key_ex = keys_ex;
796*de1e4e89SAndroid Build Coastguard Worker
797*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < sel->nkeys; i++, key++) {
798*de1e4e89SAndroid Build Coastguard Worker enum pedit_header_type htype =
799*de1e4e89SAndroid Build Coastguard Worker TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK;
800*de1e4e89SAndroid Build Coastguard Worker enum pedit_cmd cmd = TCA_PEDIT_KEY_EX_CMD_SET;
801*de1e4e89SAndroid Build Coastguard Worker
802*de1e4e89SAndroid Build Coastguard Worker if (keys_ex) {
803*de1e4e89SAndroid Build Coastguard Worker htype = key_ex->htype;
804*de1e4e89SAndroid Build Coastguard Worker cmd = key_ex->cmd;
805*de1e4e89SAndroid Build Coastguard Worker
806*de1e4e89SAndroid Build Coastguard Worker key_ex++;
807*de1e4e89SAndroid Build Coastguard Worker }
808*de1e4e89SAndroid Build Coastguard Worker
809*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n\t key #%d", i);
810*de1e4e89SAndroid Build Coastguard Worker
811*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " at ");
812*de1e4e89SAndroid Build Coastguard Worker
813*de1e4e89SAndroid Build Coastguard Worker print_pedit_location(f, htype, key->off);
814*de1e4e89SAndroid Build Coastguard Worker
815*de1e4e89SAndroid Build Coastguard Worker fprintf(f, ": %s %08x mask %08x",
816*de1e4e89SAndroid Build Coastguard Worker cmd ? "add" : "val",
817*de1e4e89SAndroid Build Coastguard Worker (unsigned int)ntohl(key->val),
818*de1e4e89SAndroid Build Coastguard Worker (unsigned int)ntohl(key->mask));
819*de1e4e89SAndroid Build Coastguard Worker }
820*de1e4e89SAndroid Build Coastguard Worker } else {
821*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\npedit %x keys %d is not LEGIT", sel->index,
822*de1e4e89SAndroid Build Coastguard Worker sel->nkeys);
823*de1e4e89SAndroid Build Coastguard Worker }
824*de1e4e89SAndroid Build Coastguard Worker
825*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n ");
826*de1e4e89SAndroid Build Coastguard Worker
827*de1e4e89SAndroid Build Coastguard Worker free(keys_ex);
828*de1e4e89SAndroid Build Coastguard Worker return 0;
829*de1e4e89SAndroid Build Coastguard Worker }
830*de1e4e89SAndroid Build Coastguard Worker
pedit_print_xstats(struct action_util * au,FILE * f,struct rtattr * xstats)831*de1e4e89SAndroid Build Coastguard Worker int pedit_print_xstats(struct action_util *au, FILE *f, struct rtattr *xstats)
832*de1e4e89SAndroid Build Coastguard Worker {
833*de1e4e89SAndroid Build Coastguard Worker return 0;
834*de1e4e89SAndroid Build Coastguard Worker }
835*de1e4e89SAndroid Build Coastguard Worker
836*de1e4e89SAndroid Build Coastguard Worker struct action_util pedit_action_util = {
837*de1e4e89SAndroid Build Coastguard Worker .id = "pedit",
838*de1e4e89SAndroid Build Coastguard Worker .parse_aopt = parse_pedit,
839*de1e4e89SAndroid Build Coastguard Worker .print_aopt = print_pedit,
840*de1e4e89SAndroid Build Coastguard Worker };
841