xref: /aosp_15_r20/external/iproute2/tc/m_mirred.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * m_egress.c		ingress/egress packet mirror/redir 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: Add Ingress support
12*de1e4e89SAndroid Build Coastguard Worker  *
13*de1e4e89SAndroid Build Coastguard Worker  */
14*de1e4e89SAndroid Build Coastguard Worker 
15*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <syslog.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
22*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
23*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
24*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
25*de1e4e89SAndroid Build Coastguard Worker #include "tc_util.h"
26*de1e4e89SAndroid Build Coastguard Worker #include "tc_common.h"
27*de1e4e89SAndroid Build Coastguard Worker #include <linux/tc_act/tc_mirred.h>
28*de1e4e89SAndroid Build Coastguard Worker 
29*de1e4e89SAndroid Build Coastguard Worker static void
explain(void)30*de1e4e89SAndroid Build Coastguard Worker explain(void)
31*de1e4e89SAndroid Build Coastguard Worker {
32*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Usage: mirred <DIRECTION> <ACTION> [index INDEX] <dev DEVICENAME>\n");
33*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "where:\n");
34*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\tDIRECTION := <ingress | egress>\n");
35*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\tACTION := <mirror | redirect>\n");
36*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\tINDEX  is the specific policy instance id\n");
37*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\tDEVICENAME is the devicename\n");
38*de1e4e89SAndroid Build Coastguard Worker 
39*de1e4e89SAndroid Build Coastguard Worker }
40*de1e4e89SAndroid Build Coastguard Worker 
41*de1e4e89SAndroid Build Coastguard Worker static void
usage(void)42*de1e4e89SAndroid Build Coastguard Worker usage(void)
43*de1e4e89SAndroid Build Coastguard Worker {
44*de1e4e89SAndroid Build Coastguard Worker 	explain();
45*de1e4e89SAndroid Build Coastguard Worker 	exit(-1);
46*de1e4e89SAndroid Build Coastguard Worker }
47*de1e4e89SAndroid Build Coastguard Worker 
mirred_n2a(int action)48*de1e4e89SAndroid Build Coastguard Worker static const char *mirred_n2a(int action)
49*de1e4e89SAndroid Build Coastguard Worker {
50*de1e4e89SAndroid Build Coastguard Worker 	switch (action) {
51*de1e4e89SAndroid Build Coastguard Worker 	case TCA_EGRESS_REDIR:
52*de1e4e89SAndroid Build Coastguard Worker 		return "Egress Redirect";
53*de1e4e89SAndroid Build Coastguard Worker 	case TCA_INGRESS_REDIR:
54*de1e4e89SAndroid Build Coastguard Worker 		return "Ingress Redirect";
55*de1e4e89SAndroid Build Coastguard Worker 	case TCA_EGRESS_MIRROR:
56*de1e4e89SAndroid Build Coastguard Worker 		return "Egress Mirror";
57*de1e4e89SAndroid Build Coastguard Worker 	case TCA_INGRESS_MIRROR:
58*de1e4e89SAndroid Build Coastguard Worker 		return "Ingress Mirror";
59*de1e4e89SAndroid Build Coastguard Worker 	default:
60*de1e4e89SAndroid Build Coastguard Worker 		return "unknown";
61*de1e4e89SAndroid Build Coastguard Worker 	}
62*de1e4e89SAndroid Build Coastguard Worker }
63*de1e4e89SAndroid Build Coastguard Worker 
64*de1e4e89SAndroid Build Coastguard Worker static int
parse_direction(struct action_util * a,int * argc_p,char *** argv_p,int tca_id,struct nlmsghdr * n)65*de1e4e89SAndroid Build Coastguard Worker parse_direction(struct action_util *a, int *argc_p, char ***argv_p,
66*de1e4e89SAndroid Build Coastguard Worker 		int tca_id, struct nlmsghdr *n)
67*de1e4e89SAndroid Build Coastguard Worker {
68*de1e4e89SAndroid Build Coastguard Worker 
69*de1e4e89SAndroid Build Coastguard Worker 	int argc = *argc_p;
70*de1e4e89SAndroid Build Coastguard Worker 	char **argv = *argv_p;
71*de1e4e89SAndroid Build Coastguard Worker 	int ok = 0, iok = 0, mirror = 0, redir = 0, ingress = 0, egress = 0;
72*de1e4e89SAndroid Build Coastguard Worker 	struct tc_mirred p = {};
73*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tail;
74*de1e4e89SAndroid Build Coastguard Worker 	char d[16] = {};
75*de1e4e89SAndroid Build Coastguard Worker 
76*de1e4e89SAndroid Build Coastguard Worker 	while (argc > 0) {
77*de1e4e89SAndroid Build Coastguard Worker 
78*de1e4e89SAndroid Build Coastguard Worker 		if (matches(*argv, "action") == 0) {
79*de1e4e89SAndroid Build Coastguard Worker 			break;
80*de1e4e89SAndroid Build Coastguard Worker 		} else if (!egress && matches(*argv, "egress") == 0) {
81*de1e4e89SAndroid Build Coastguard Worker 			egress = 1;
82*de1e4e89SAndroid Build Coastguard Worker 			if (ingress) {
83*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Can't have both egress and ingress\n");
84*de1e4e89SAndroid Build Coastguard Worker 				return -1;
85*de1e4e89SAndroid Build Coastguard Worker 			}
86*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
87*de1e4e89SAndroid Build Coastguard Worker 			ok++;
88*de1e4e89SAndroid Build Coastguard Worker 			continue;
89*de1e4e89SAndroid Build Coastguard Worker 		} else if (!ingress && matches(*argv, "ingress") == 0) {
90*de1e4e89SAndroid Build Coastguard Worker 			ingress = 1;
91*de1e4e89SAndroid Build Coastguard Worker 			if (egress) {
92*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Can't have both ingress and egress\n");
93*de1e4e89SAndroid Build Coastguard Worker 				return -1;
94*de1e4e89SAndroid Build Coastguard Worker 			}
95*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
96*de1e4e89SAndroid Build Coastguard Worker 			ok++;
97*de1e4e89SAndroid Build Coastguard Worker 			continue;
98*de1e4e89SAndroid Build Coastguard Worker 		} else {
99*de1e4e89SAndroid Build Coastguard Worker 
100*de1e4e89SAndroid Build Coastguard Worker 			if (matches(*argv, "index") == 0) {
101*de1e4e89SAndroid Build Coastguard Worker 				NEXT_ARG();
102*de1e4e89SAndroid Build Coastguard Worker 				if (get_u32(&p.index, *argv, 10)) {
103*de1e4e89SAndroid Build Coastguard Worker 					fprintf(stderr, "Illegal \"index\"\n");
104*de1e4e89SAndroid Build Coastguard Worker 					return -1;
105*de1e4e89SAndroid Build Coastguard Worker 				}
106*de1e4e89SAndroid Build Coastguard Worker 				iok++;
107*de1e4e89SAndroid Build Coastguard Worker 				if (!ok) {
108*de1e4e89SAndroid Build Coastguard Worker 					argc--;
109*de1e4e89SAndroid Build Coastguard Worker 					argv++;
110*de1e4e89SAndroid Build Coastguard Worker 					break;
111*de1e4e89SAndroid Build Coastguard Worker 				}
112*de1e4e89SAndroid Build Coastguard Worker 			} else if (!ok) {
113*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "was expecting egress or ingress (%s)\n", *argv);
114*de1e4e89SAndroid Build Coastguard Worker 				break;
115*de1e4e89SAndroid Build Coastguard Worker 
116*de1e4e89SAndroid Build Coastguard Worker 			} else if (!mirror && matches(*argv, "mirror") == 0) {
117*de1e4e89SAndroid Build Coastguard Worker 				mirror = 1;
118*de1e4e89SAndroid Build Coastguard Worker 				if (redir) {
119*de1e4e89SAndroid Build Coastguard Worker 					fprintf(stderr, "Can't have both mirror and redir\n");
120*de1e4e89SAndroid Build Coastguard Worker 					return -1;
121*de1e4e89SAndroid Build Coastguard Worker 				}
122*de1e4e89SAndroid Build Coastguard Worker 				p.eaction = egress ? TCA_EGRESS_MIRROR :
123*de1e4e89SAndroid Build Coastguard Worker 					    TCA_INGRESS_MIRROR;
124*de1e4e89SAndroid Build Coastguard Worker 				p.action = TC_ACT_PIPE;
125*de1e4e89SAndroid Build Coastguard Worker 				ok++;
126*de1e4e89SAndroid Build Coastguard Worker 			} else if (!redir && matches(*argv, "redirect") == 0) {
127*de1e4e89SAndroid Build Coastguard Worker 				redir = 1;
128*de1e4e89SAndroid Build Coastguard Worker 				if (mirror) {
129*de1e4e89SAndroid Build Coastguard Worker 					fprintf(stderr, "Can't have both mirror and redir\n");
130*de1e4e89SAndroid Build Coastguard Worker 					return -1;
131*de1e4e89SAndroid Build Coastguard Worker 				}
132*de1e4e89SAndroid Build Coastguard Worker 				p.eaction = egress ? TCA_EGRESS_REDIR :
133*de1e4e89SAndroid Build Coastguard Worker 					    TCA_INGRESS_REDIR;
134*de1e4e89SAndroid Build Coastguard Worker 				p.action = TC_ACT_STOLEN;
135*de1e4e89SAndroid Build Coastguard Worker 				ok++;
136*de1e4e89SAndroid Build Coastguard Worker 			} else if ((redir || mirror) && matches(*argv, "dev") == 0) {
137*de1e4e89SAndroid Build Coastguard Worker 				NEXT_ARG();
138*de1e4e89SAndroid Build Coastguard Worker 				if (strlen(d))
139*de1e4e89SAndroid Build Coastguard Worker 					duparg("dev", *argv);
140*de1e4e89SAndroid Build Coastguard Worker 
141*de1e4e89SAndroid Build Coastguard Worker 				strncpy(d, *argv, sizeof(d)-1);
142*de1e4e89SAndroid Build Coastguard Worker 				argc--;
143*de1e4e89SAndroid Build Coastguard Worker 				argv++;
144*de1e4e89SAndroid Build Coastguard Worker 
145*de1e4e89SAndroid Build Coastguard Worker 				break;
146*de1e4e89SAndroid Build Coastguard Worker 
147*de1e4e89SAndroid Build Coastguard Worker 			}
148*de1e4e89SAndroid Build Coastguard Worker 		}
149*de1e4e89SAndroid Build Coastguard Worker 
150*de1e4e89SAndroid Build Coastguard Worker 		NEXT_ARG();
151*de1e4e89SAndroid Build Coastguard Worker 	}
152*de1e4e89SAndroid Build Coastguard Worker 
153*de1e4e89SAndroid Build Coastguard Worker 	if (!ok && !iok) {
154*de1e4e89SAndroid Build Coastguard Worker 		return -1;
155*de1e4e89SAndroid Build Coastguard Worker 	}
156*de1e4e89SAndroid Build Coastguard Worker 
157*de1e4e89SAndroid Build Coastguard Worker 
158*de1e4e89SAndroid Build Coastguard Worker 
159*de1e4e89SAndroid Build Coastguard Worker 	if (d[0])  {
160*de1e4e89SAndroid Build Coastguard Worker 		int idx;
161*de1e4e89SAndroid Build Coastguard Worker 
162*de1e4e89SAndroid Build Coastguard Worker 		ll_init_map(&rth);
163*de1e4e89SAndroid Build Coastguard Worker 
164*de1e4e89SAndroid Build Coastguard Worker 		if ((idx = ll_name_to_index(d)) == 0) {
165*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Cannot find device \"%s\"\n", d);
166*de1e4e89SAndroid Build Coastguard Worker 			return -1;
167*de1e4e89SAndroid Build Coastguard Worker 		}
168*de1e4e89SAndroid Build Coastguard Worker 
169*de1e4e89SAndroid Build Coastguard Worker 		p.ifindex = idx;
170*de1e4e89SAndroid Build Coastguard Worker 	}
171*de1e4e89SAndroid Build Coastguard Worker 
172*de1e4e89SAndroid Build Coastguard Worker 
173*de1e4e89SAndroid Build Coastguard Worker 	if (p.eaction == TCA_EGRESS_MIRROR || p.eaction == TCA_INGRESS_MIRROR)
174*de1e4e89SAndroid Build Coastguard Worker 		parse_action_control(&argc, &argv, &p.action, false);
175*de1e4e89SAndroid Build Coastguard Worker 
176*de1e4e89SAndroid Build Coastguard Worker 	if (argc) {
177*de1e4e89SAndroid Build Coastguard Worker 		if (iok && matches(*argv, "index") == 0) {
178*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "mirred: Illegal double index\n");
179*de1e4e89SAndroid Build Coastguard Worker 			return -1;
180*de1e4e89SAndroid Build Coastguard Worker 		} else {
181*de1e4e89SAndroid Build Coastguard Worker 			if (matches(*argv, "index") == 0) {
182*de1e4e89SAndroid Build Coastguard Worker 				NEXT_ARG();
183*de1e4e89SAndroid Build Coastguard Worker 				if (get_u32(&p.index, *argv, 10)) {
184*de1e4e89SAndroid Build Coastguard Worker 					fprintf(stderr, "mirred: Illegal \"index\"\n");
185*de1e4e89SAndroid Build Coastguard Worker 					return -1;
186*de1e4e89SAndroid Build Coastguard Worker 				}
187*de1e4e89SAndroid Build Coastguard Worker 				argc--;
188*de1e4e89SAndroid Build Coastguard Worker 				argv++;
189*de1e4e89SAndroid Build Coastguard Worker 			}
190*de1e4e89SAndroid Build Coastguard Worker 		}
191*de1e4e89SAndroid Build Coastguard Worker 	}
192*de1e4e89SAndroid Build Coastguard Worker 
193*de1e4e89SAndroid Build Coastguard Worker 	tail = NLMSG_TAIL(n);
194*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
195*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(n, MAX_MSG, TCA_MIRRED_PARMS, &p, sizeof(p));
196*de1e4e89SAndroid Build Coastguard Worker 	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
197*de1e4e89SAndroid Build Coastguard Worker 
198*de1e4e89SAndroid Build Coastguard Worker 	*argc_p = argc;
199*de1e4e89SAndroid Build Coastguard Worker 	*argv_p = argv;
200*de1e4e89SAndroid Build Coastguard Worker 	return 0;
201*de1e4e89SAndroid Build Coastguard Worker }
202*de1e4e89SAndroid Build Coastguard Worker 
203*de1e4e89SAndroid Build Coastguard Worker 
204*de1e4e89SAndroid Build Coastguard Worker static int
parse_mirred(struct action_util * a,int * argc_p,char *** argv_p,int tca_id,struct nlmsghdr * n)205*de1e4e89SAndroid Build Coastguard Worker parse_mirred(struct action_util *a, int *argc_p, char ***argv_p,
206*de1e4e89SAndroid Build Coastguard Worker 	     int tca_id, struct nlmsghdr *n)
207*de1e4e89SAndroid Build Coastguard Worker {
208*de1e4e89SAndroid Build Coastguard Worker 
209*de1e4e89SAndroid Build Coastguard Worker 	int argc = *argc_p;
210*de1e4e89SAndroid Build Coastguard Worker 	char **argv = *argv_p;
211*de1e4e89SAndroid Build Coastguard Worker 
212*de1e4e89SAndroid Build Coastguard Worker 	if (argc < 0) {
213*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "mirred bad argument count %d\n", argc);
214*de1e4e89SAndroid Build Coastguard Worker 		return -1;
215*de1e4e89SAndroid Build Coastguard Worker 	}
216*de1e4e89SAndroid Build Coastguard Worker 
217*de1e4e89SAndroid Build Coastguard Worker 	if (matches(*argv, "mirred") == 0) {
218*de1e4e89SAndroid Build Coastguard Worker 		NEXT_ARG();
219*de1e4e89SAndroid Build Coastguard Worker 	} else {
220*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "mirred bad argument %s\n", *argv);
221*de1e4e89SAndroid Build Coastguard Worker 		return -1;
222*de1e4e89SAndroid Build Coastguard Worker 	}
223*de1e4e89SAndroid Build Coastguard Worker 
224*de1e4e89SAndroid Build Coastguard Worker 
225*de1e4e89SAndroid Build Coastguard Worker 	if (matches(*argv, "egress") == 0 || matches(*argv, "ingress") == 0 ||
226*de1e4e89SAndroid Build Coastguard Worker 	    matches(*argv, "index") == 0) {
227*de1e4e89SAndroid Build Coastguard Worker 		int ret = parse_direction(a, &argc, &argv, tca_id, n);
228*de1e4e89SAndroid Build Coastguard Worker 
229*de1e4e89SAndroid Build Coastguard Worker 		if (ret == 0) {
230*de1e4e89SAndroid Build Coastguard Worker 			*argc_p = argc;
231*de1e4e89SAndroid Build Coastguard Worker 			*argv_p = argv;
232*de1e4e89SAndroid Build Coastguard Worker 			return 0;
233*de1e4e89SAndroid Build Coastguard Worker 		}
234*de1e4e89SAndroid Build Coastguard Worker 
235*de1e4e89SAndroid Build Coastguard Worker 	} else if (matches(*argv, "help") == 0) {
236*de1e4e89SAndroid Build Coastguard Worker 		usage();
237*de1e4e89SAndroid Build Coastguard Worker 	} else {
238*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "mirred option not supported %s\n", *argv);
239*de1e4e89SAndroid Build Coastguard Worker 	}
240*de1e4e89SAndroid Build Coastguard Worker 
241*de1e4e89SAndroid Build Coastguard Worker 	return -1;
242*de1e4e89SAndroid Build Coastguard Worker 
243*de1e4e89SAndroid Build Coastguard Worker }
244*de1e4e89SAndroid Build Coastguard Worker 
245*de1e4e89SAndroid Build Coastguard Worker static int
print_mirred(struct action_util * au,FILE * f,struct rtattr * arg)246*de1e4e89SAndroid Build Coastguard Worker print_mirred(struct action_util *au, FILE * f, struct rtattr *arg)
247*de1e4e89SAndroid Build Coastguard Worker {
248*de1e4e89SAndroid Build Coastguard Worker 	struct tc_mirred *p;
249*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tb[TCA_MIRRED_MAX + 1];
250*de1e4e89SAndroid Build Coastguard Worker 	const char *dev;
251*de1e4e89SAndroid Build Coastguard Worker 
252*de1e4e89SAndroid Build Coastguard Worker 	if (arg == NULL)
253*de1e4e89SAndroid Build Coastguard Worker 		return -1;
254*de1e4e89SAndroid Build Coastguard Worker 
255*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr_nested(tb, TCA_MIRRED_MAX, arg);
256*de1e4e89SAndroid Build Coastguard Worker 
257*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_MIRRED_PARMS] == NULL) {
258*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "[NULL mirred parameters]");
259*de1e4e89SAndroid Build Coastguard Worker 		return -1;
260*de1e4e89SAndroid Build Coastguard Worker 	}
261*de1e4e89SAndroid Build Coastguard Worker 	p = RTA_DATA(tb[TCA_MIRRED_PARMS]);
262*de1e4e89SAndroid Build Coastguard Worker 
263*de1e4e89SAndroid Build Coastguard Worker 	/*
264*de1e4e89SAndroid Build Coastguard Worker 	ll_init_map(&rth);
265*de1e4e89SAndroid Build Coastguard Worker 	*/
266*de1e4e89SAndroid Build Coastguard Worker 
267*de1e4e89SAndroid Build Coastguard Worker 
268*de1e4e89SAndroid Build Coastguard Worker 	if ((dev = ll_index_to_name(p->ifindex)) == 0) {
269*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Cannot find device %d\n", p->ifindex);
270*de1e4e89SAndroid Build Coastguard Worker 		return -1;
271*de1e4e89SAndroid Build Coastguard Worker 	}
272*de1e4e89SAndroid Build Coastguard Worker 
273*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, "mirred (%s to device %s)", mirred_n2a(p->eaction), dev);
274*de1e4e89SAndroid Build Coastguard Worker 	print_action_control(f, " ", p->action, "");
275*de1e4e89SAndroid Build Coastguard Worker 
276*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, "\n ");
277*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, "\tindex %u ref %d bind %d", p->index, p->refcnt,
278*de1e4e89SAndroid Build Coastguard Worker 		p->bindcnt);
279*de1e4e89SAndroid Build Coastguard Worker 
280*de1e4e89SAndroid Build Coastguard Worker 	if (show_stats) {
281*de1e4e89SAndroid Build Coastguard Worker 		if (tb[TCA_MIRRED_TM]) {
282*de1e4e89SAndroid Build Coastguard Worker 			struct tcf_t *tm = RTA_DATA(tb[TCA_MIRRED_TM]);
283*de1e4e89SAndroid Build Coastguard Worker 
284*de1e4e89SAndroid Build Coastguard Worker 			print_tm(f, tm);
285*de1e4e89SAndroid Build Coastguard Worker 		}
286*de1e4e89SAndroid Build Coastguard Worker 	}
287*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, "\n ");
288*de1e4e89SAndroid Build Coastguard Worker 	return 0;
289*de1e4e89SAndroid Build Coastguard Worker }
290*de1e4e89SAndroid Build Coastguard Worker 
291*de1e4e89SAndroid Build Coastguard Worker struct action_util mirred_action_util = {
292*de1e4e89SAndroid Build Coastguard Worker 	.id = "mirred",
293*de1e4e89SAndroid Build Coastguard Worker 	.parse_aopt = parse_mirred,
294*de1e4e89SAndroid Build Coastguard Worker 	.print_aopt = print_mirred,
295*de1e4e89SAndroid Build Coastguard Worker };
296