xref: /aosp_15_r20/external/iptables/extensions/libxt_CT.c (revision a71a954618bbadd4a345637e5edcf36eec826889)
1*a71a9546SAutomerger Merge Worker /*
2*a71a9546SAutomerger Merge Worker  * Copyright (c) 2010-2013 Patrick McHardy <[email protected]>
3*a71a9546SAutomerger Merge Worker  */
4*a71a9546SAutomerger Merge Worker 
5*a71a9546SAutomerger Merge Worker #include <stdio.h>
6*a71a9546SAutomerger Merge Worker #include <string.h>
7*a71a9546SAutomerger Merge Worker #include <xtables.h>
8*a71a9546SAutomerger Merge Worker #include <linux/netfilter/nf_conntrack_common.h>
9*a71a9546SAutomerger Merge Worker #include <linux/netfilter/xt_CT.h>
10*a71a9546SAutomerger Merge Worker 
ct_help(void)11*a71a9546SAutomerger Merge Worker static void ct_help(void)
12*a71a9546SAutomerger Merge Worker {
13*a71a9546SAutomerger Merge Worker 	printf(
14*a71a9546SAutomerger Merge Worker "CT target options:\n"
15*a71a9546SAutomerger Merge Worker " --notrack			Don't track connection\n"
16*a71a9546SAutomerger Merge Worker " --helper name			Use conntrack helper 'name' for connection\n"
17*a71a9546SAutomerger Merge Worker " --ctevents event[,event...]	Generate specified conntrack events for connection\n"
18*a71a9546SAutomerger Merge Worker " --expevents event[,event...]	Generate specified expectation events for connection\n"
19*a71a9546SAutomerger Merge Worker " --zone {ID|mark}		Assign/Lookup connection in zone ID/packet nfmark\n"
20*a71a9546SAutomerger Merge Worker " --zone-orig {ID|mark}		Same as 'zone' option, but only applies to ORIGINAL direction\n"
21*a71a9546SAutomerger Merge Worker " --zone-reply {ID|mark} 	Same as 'zone' option, but only applies to REPLY direction\n"
22*a71a9546SAutomerger Merge Worker 	);
23*a71a9546SAutomerger Merge Worker }
24*a71a9546SAutomerger Merge Worker 
ct_help_v1(void)25*a71a9546SAutomerger Merge Worker static void ct_help_v1(void)
26*a71a9546SAutomerger Merge Worker {
27*a71a9546SAutomerger Merge Worker 	printf(
28*a71a9546SAutomerger Merge Worker "CT target options:\n"
29*a71a9546SAutomerger Merge Worker " --notrack			Don't track connection\n"
30*a71a9546SAutomerger Merge Worker " --helper name			Use conntrack helper 'name' for connection\n"
31*a71a9546SAutomerger Merge Worker " --timeout name 		Use timeout policy 'name' for connection\n"
32*a71a9546SAutomerger Merge Worker " --ctevents event[,event...]	Generate specified conntrack events for connection\n"
33*a71a9546SAutomerger Merge Worker " --expevents event[,event...]	Generate specified expectation events for connection\n"
34*a71a9546SAutomerger Merge Worker " --zone {ID|mark}		Assign/Lookup connection in zone ID/packet nfmark\n"
35*a71a9546SAutomerger Merge Worker " --zone-orig {ID|mark}		Same as 'zone' option, but only applies to ORIGINAL direction\n"
36*a71a9546SAutomerger Merge Worker " --zone-reply {ID|mark} 	Same as 'zone' option, but only applies to REPLY direction\n"
37*a71a9546SAutomerger Merge Worker 	);
38*a71a9546SAutomerger Merge Worker }
39*a71a9546SAutomerger Merge Worker 
40*a71a9546SAutomerger Merge Worker enum {
41*a71a9546SAutomerger Merge Worker 	O_NOTRACK = 0,
42*a71a9546SAutomerger Merge Worker 	O_HELPER,
43*a71a9546SAutomerger Merge Worker 	O_TIMEOUT,
44*a71a9546SAutomerger Merge Worker 	O_CTEVENTS,
45*a71a9546SAutomerger Merge Worker 	O_EXPEVENTS,
46*a71a9546SAutomerger Merge Worker 	O_ZONE,
47*a71a9546SAutomerger Merge Worker 	O_ZONE_ORIG,
48*a71a9546SAutomerger Merge Worker 	O_ZONE_REPLY,
49*a71a9546SAutomerger Merge Worker };
50*a71a9546SAutomerger Merge Worker 
51*a71a9546SAutomerger Merge Worker #define s struct xt_ct_target_info
52*a71a9546SAutomerger Merge Worker static const struct xt_option_entry ct_opts[] = {
53*a71a9546SAutomerger Merge Worker 	{.name = "notrack", .id = O_NOTRACK, .type = XTTYPE_NONE},
54*a71a9546SAutomerger Merge Worker 	{.name = "helper", .id = O_HELPER, .type = XTTYPE_STRING,
55*a71a9546SAutomerger Merge Worker 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, helper)},
56*a71a9546SAutomerger Merge Worker 	{.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING},
57*a71a9546SAutomerger Merge Worker 	{.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING},
58*a71a9546SAutomerger Merge Worker 	{.name = "zone-orig", .id = O_ZONE_ORIG, .type = XTTYPE_STRING},
59*a71a9546SAutomerger Merge Worker 	{.name = "zone-reply", .id = O_ZONE_REPLY, .type = XTTYPE_STRING},
60*a71a9546SAutomerger Merge Worker 	{.name = "zone", .id = O_ZONE, .type = XTTYPE_STRING},
61*a71a9546SAutomerger Merge Worker 	XTOPT_TABLEEND,
62*a71a9546SAutomerger Merge Worker };
63*a71a9546SAutomerger Merge Worker #undef s
64*a71a9546SAutomerger Merge Worker 
65*a71a9546SAutomerger Merge Worker #define s struct xt_ct_target_info_v1
66*a71a9546SAutomerger Merge Worker static const struct xt_option_entry ct_opts_v1[] = {
67*a71a9546SAutomerger Merge Worker 	{.name = "notrack", .id = O_NOTRACK, .type = XTTYPE_NONE},
68*a71a9546SAutomerger Merge Worker 	{.name = "helper", .id = O_HELPER, .type = XTTYPE_STRING,
69*a71a9546SAutomerger Merge Worker 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, helper)},
70*a71a9546SAutomerger Merge Worker 	{.name = "timeout", .id = O_TIMEOUT, .type = XTTYPE_STRING,
71*a71a9546SAutomerger Merge Worker 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, timeout)},
72*a71a9546SAutomerger Merge Worker 	{.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING},
73*a71a9546SAutomerger Merge Worker 	{.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING},
74*a71a9546SAutomerger Merge Worker 	{.name = "zone-orig", .id = O_ZONE_ORIG, .type = XTTYPE_STRING},
75*a71a9546SAutomerger Merge Worker 	{.name = "zone-reply", .id = O_ZONE_REPLY, .type = XTTYPE_STRING},
76*a71a9546SAutomerger Merge Worker 	{.name = "zone", .id = O_ZONE, .type = XTTYPE_STRING},
77*a71a9546SAutomerger Merge Worker 	XTOPT_TABLEEND,
78*a71a9546SAutomerger Merge Worker };
79*a71a9546SAutomerger Merge Worker #undef s
80*a71a9546SAutomerger Merge Worker 
81*a71a9546SAutomerger Merge Worker struct event_tbl {
82*a71a9546SAutomerger Merge Worker 	const char	*name;
83*a71a9546SAutomerger Merge Worker 	unsigned int	event;
84*a71a9546SAutomerger Merge Worker };
85*a71a9546SAutomerger Merge Worker 
86*a71a9546SAutomerger Merge Worker static const struct event_tbl ct_event_tbl[] = {
87*a71a9546SAutomerger Merge Worker 	{ "new",		IPCT_NEW },
88*a71a9546SAutomerger Merge Worker 	{ "related",		IPCT_RELATED },
89*a71a9546SAutomerger Merge Worker 	{ "destroy",		IPCT_DESTROY },
90*a71a9546SAutomerger Merge Worker 	{ "reply",		IPCT_REPLY },
91*a71a9546SAutomerger Merge Worker 	{ "assured",		IPCT_ASSURED },
92*a71a9546SAutomerger Merge Worker 	{ "protoinfo",		IPCT_PROTOINFO },
93*a71a9546SAutomerger Merge Worker 	{ "helper",		IPCT_HELPER },
94*a71a9546SAutomerger Merge Worker 	{ "mark",		IPCT_MARK },
95*a71a9546SAutomerger Merge Worker 	{ "natseqinfo",		IPCT_NATSEQADJ },
96*a71a9546SAutomerger Merge Worker 	{ "secmark",		IPCT_SECMARK },
97*a71a9546SAutomerger Merge Worker };
98*a71a9546SAutomerger Merge Worker 
99*a71a9546SAutomerger Merge Worker static const struct event_tbl exp_event_tbl[] = {
100*a71a9546SAutomerger Merge Worker 	{ "new",		IPEXP_NEW },
101*a71a9546SAutomerger Merge Worker };
102*a71a9546SAutomerger Merge Worker 
ct_parse_zone_id(const char * opt,unsigned int opt_id,uint16_t * zone_id,uint16_t * flags)103*a71a9546SAutomerger Merge Worker static void ct_parse_zone_id(const char *opt, unsigned int opt_id,
104*a71a9546SAutomerger Merge Worker 			     uint16_t *zone_id, uint16_t *flags)
105*a71a9546SAutomerger Merge Worker {
106*a71a9546SAutomerger Merge Worker 	if (opt_id == O_ZONE_ORIG)
107*a71a9546SAutomerger Merge Worker 		*flags |= XT_CT_ZONE_DIR_ORIG;
108*a71a9546SAutomerger Merge Worker 	if (opt_id == O_ZONE_REPLY)
109*a71a9546SAutomerger Merge Worker 		*flags |= XT_CT_ZONE_DIR_REPL;
110*a71a9546SAutomerger Merge Worker 
111*a71a9546SAutomerger Merge Worker 	*zone_id = 0;
112*a71a9546SAutomerger Merge Worker 
113*a71a9546SAutomerger Merge Worker 	if (strcasecmp(opt, "mark") == 0) {
114*a71a9546SAutomerger Merge Worker 		*flags |= XT_CT_ZONE_MARK;
115*a71a9546SAutomerger Merge Worker 	} else {
116*a71a9546SAutomerger Merge Worker 		uintmax_t val;
117*a71a9546SAutomerger Merge Worker 
118*a71a9546SAutomerger Merge Worker 		if (!xtables_strtoul(opt, NULL, &val, 0, UINT16_MAX))
119*a71a9546SAutomerger Merge Worker 			xtables_error(PARAMETER_PROBLEM,
120*a71a9546SAutomerger Merge Worker 				      "Cannot parse %s as a zone ID", opt);
121*a71a9546SAutomerger Merge Worker 
122*a71a9546SAutomerger Merge Worker 		*zone_id = (uint16_t)val;
123*a71a9546SAutomerger Merge Worker 	}
124*a71a9546SAutomerger Merge Worker }
125*a71a9546SAutomerger Merge Worker 
ct_print_zone_id(const char * pfx,uint16_t zone_id,uint16_t flags)126*a71a9546SAutomerger Merge Worker static void ct_print_zone_id(const char *pfx, uint16_t zone_id, uint16_t flags)
127*a71a9546SAutomerger Merge Worker {
128*a71a9546SAutomerger Merge Worker 	printf(" %s", pfx);
129*a71a9546SAutomerger Merge Worker 
130*a71a9546SAutomerger Merge Worker 	if ((flags & (XT_CT_ZONE_DIR_ORIG |
131*a71a9546SAutomerger Merge Worker 		      XT_CT_ZONE_DIR_REPL)) == XT_CT_ZONE_DIR_ORIG)
132*a71a9546SAutomerger Merge Worker 		printf("-orig");
133*a71a9546SAutomerger Merge Worker 	if ((flags & (XT_CT_ZONE_DIR_ORIG |
134*a71a9546SAutomerger Merge Worker 		      XT_CT_ZONE_DIR_REPL)) == XT_CT_ZONE_DIR_REPL)
135*a71a9546SAutomerger Merge Worker 		printf("-reply");
136*a71a9546SAutomerger Merge Worker 	if (flags & XT_CT_ZONE_MARK)
137*a71a9546SAutomerger Merge Worker 		printf(" mark");
138*a71a9546SAutomerger Merge Worker 	else
139*a71a9546SAutomerger Merge Worker 		printf(" %u", zone_id);
140*a71a9546SAutomerger Merge Worker }
141*a71a9546SAutomerger Merge Worker 
ct_parse_events(const struct event_tbl * tbl,unsigned int size,const char * events)142*a71a9546SAutomerger Merge Worker static uint32_t ct_parse_events(const struct event_tbl *tbl, unsigned int size,
143*a71a9546SAutomerger Merge Worker 				const char *events)
144*a71a9546SAutomerger Merge Worker {
145*a71a9546SAutomerger Merge Worker 	char str[strlen(events) + 1], *e = str, *t;
146*a71a9546SAutomerger Merge Worker 	unsigned int mask = 0, i;
147*a71a9546SAutomerger Merge Worker 
148*a71a9546SAutomerger Merge Worker 	strcpy(str, events);
149*a71a9546SAutomerger Merge Worker 	while ((t = strsep(&e, ","))) {
150*a71a9546SAutomerger Merge Worker 		for (i = 0; i < size; i++) {
151*a71a9546SAutomerger Merge Worker 			if (strcmp(t, tbl[i].name))
152*a71a9546SAutomerger Merge Worker 				continue;
153*a71a9546SAutomerger Merge Worker 			mask |= 1 << tbl[i].event;
154*a71a9546SAutomerger Merge Worker 			break;
155*a71a9546SAutomerger Merge Worker 		}
156*a71a9546SAutomerger Merge Worker 
157*a71a9546SAutomerger Merge Worker 		if (i == size)
158*a71a9546SAutomerger Merge Worker 			xtables_error(PARAMETER_PROBLEM, "Unknown event type \"%s\"", t);
159*a71a9546SAutomerger Merge Worker 	}
160*a71a9546SAutomerger Merge Worker 
161*a71a9546SAutomerger Merge Worker 	return mask;
162*a71a9546SAutomerger Merge Worker }
163*a71a9546SAutomerger Merge Worker 
ct_print_events(const char * pfx,const struct event_tbl * tbl,unsigned int size,uint32_t mask)164*a71a9546SAutomerger Merge Worker static void ct_print_events(const char *pfx, const struct event_tbl *tbl,
165*a71a9546SAutomerger Merge Worker 			    unsigned int size, uint32_t mask)
166*a71a9546SAutomerger Merge Worker {
167*a71a9546SAutomerger Merge Worker 	const char *sep = "";
168*a71a9546SAutomerger Merge Worker 	unsigned int i;
169*a71a9546SAutomerger Merge Worker 
170*a71a9546SAutomerger Merge Worker 	printf(" %s ", pfx);
171*a71a9546SAutomerger Merge Worker 	for (i = 0; i < size; i++) {
172*a71a9546SAutomerger Merge Worker 		if (mask & (1 << tbl[i].event)) {
173*a71a9546SAutomerger Merge Worker 			printf("%s%s", sep, tbl[i].name);
174*a71a9546SAutomerger Merge Worker 			sep = ",";
175*a71a9546SAutomerger Merge Worker 		}
176*a71a9546SAutomerger Merge Worker 	}
177*a71a9546SAutomerger Merge Worker }
178*a71a9546SAutomerger Merge Worker 
ct_parse(struct xt_option_call * cb)179*a71a9546SAutomerger Merge Worker static void ct_parse(struct xt_option_call *cb)
180*a71a9546SAutomerger Merge Worker {
181*a71a9546SAutomerger Merge Worker 	struct xt_ct_target_info *info = cb->data;
182*a71a9546SAutomerger Merge Worker 
183*a71a9546SAutomerger Merge Worker 	xtables_option_parse(cb);
184*a71a9546SAutomerger Merge Worker 	switch (cb->entry->id) {
185*a71a9546SAutomerger Merge Worker 	case O_NOTRACK:
186*a71a9546SAutomerger Merge Worker 		info->flags |= XT_CT_NOTRACK;
187*a71a9546SAutomerger Merge Worker 		break;
188*a71a9546SAutomerger Merge Worker 	case O_ZONE_ORIG:
189*a71a9546SAutomerger Merge Worker 	case O_ZONE_REPLY:
190*a71a9546SAutomerger Merge Worker 	case O_ZONE:
191*a71a9546SAutomerger Merge Worker 		ct_parse_zone_id(cb->arg, cb->entry->id, &info->zone,
192*a71a9546SAutomerger Merge Worker 				 &info->flags);
193*a71a9546SAutomerger Merge Worker 		break;
194*a71a9546SAutomerger Merge Worker 	case O_CTEVENTS:
195*a71a9546SAutomerger Merge Worker 		info->ct_events = ct_parse_events(ct_event_tbl, ARRAY_SIZE(ct_event_tbl), cb->arg);
196*a71a9546SAutomerger Merge Worker 		break;
197*a71a9546SAutomerger Merge Worker 	case O_EXPEVENTS:
198*a71a9546SAutomerger Merge Worker 		info->exp_events = ct_parse_events(exp_event_tbl, ARRAY_SIZE(exp_event_tbl), cb->arg);
199*a71a9546SAutomerger Merge Worker 		break;
200*a71a9546SAutomerger Merge Worker 	}
201*a71a9546SAutomerger Merge Worker }
202*a71a9546SAutomerger Merge Worker 
ct_parse_v1(struct xt_option_call * cb)203*a71a9546SAutomerger Merge Worker static void ct_parse_v1(struct xt_option_call *cb)
204*a71a9546SAutomerger Merge Worker {
205*a71a9546SAutomerger Merge Worker 	struct xt_ct_target_info_v1 *info = cb->data;
206*a71a9546SAutomerger Merge Worker 
207*a71a9546SAutomerger Merge Worker 	xtables_option_parse(cb);
208*a71a9546SAutomerger Merge Worker 	switch (cb->entry->id) {
209*a71a9546SAutomerger Merge Worker 	case O_NOTRACK:
210*a71a9546SAutomerger Merge Worker 		info->flags |= XT_CT_NOTRACK;
211*a71a9546SAutomerger Merge Worker 		break;
212*a71a9546SAutomerger Merge Worker 	case O_ZONE_ORIG:
213*a71a9546SAutomerger Merge Worker 	case O_ZONE_REPLY:
214*a71a9546SAutomerger Merge Worker 	case O_ZONE:
215*a71a9546SAutomerger Merge Worker 		ct_parse_zone_id(cb->arg, cb->entry->id, &info->zone,
216*a71a9546SAutomerger Merge Worker 				 &info->flags);
217*a71a9546SAutomerger Merge Worker 		break;
218*a71a9546SAutomerger Merge Worker 	case O_CTEVENTS:
219*a71a9546SAutomerger Merge Worker 		info->ct_events = ct_parse_events(ct_event_tbl,
220*a71a9546SAutomerger Merge Worker 						  ARRAY_SIZE(ct_event_tbl),
221*a71a9546SAutomerger Merge Worker 						  cb->arg);
222*a71a9546SAutomerger Merge Worker 		break;
223*a71a9546SAutomerger Merge Worker 	case O_EXPEVENTS:
224*a71a9546SAutomerger Merge Worker 		info->exp_events = ct_parse_events(exp_event_tbl,
225*a71a9546SAutomerger Merge Worker 						   ARRAY_SIZE(exp_event_tbl),
226*a71a9546SAutomerger Merge Worker 						   cb->arg);
227*a71a9546SAutomerger Merge Worker 		break;
228*a71a9546SAutomerger Merge Worker 	}
229*a71a9546SAutomerger Merge Worker }
230*a71a9546SAutomerger Merge Worker 
ct_print(const void * ip,const struct xt_entry_target * target,int numeric)231*a71a9546SAutomerger Merge Worker static void ct_print(const void *ip, const struct xt_entry_target *target, int numeric)
232*a71a9546SAutomerger Merge Worker {
233*a71a9546SAutomerger Merge Worker 	const struct xt_ct_target_info *info =
234*a71a9546SAutomerger Merge Worker 		(const struct xt_ct_target_info *)target->data;
235*a71a9546SAutomerger Merge Worker 
236*a71a9546SAutomerger Merge Worker 	printf(" CT");
237*a71a9546SAutomerger Merge Worker 	if (info->flags & XT_CT_NOTRACK)
238*a71a9546SAutomerger Merge Worker 		printf(" notrack");
239*a71a9546SAutomerger Merge Worker 	if (info->helper[0])
240*a71a9546SAutomerger Merge Worker 		printf(" helper %s", info->helper);
241*a71a9546SAutomerger Merge Worker 	if (info->ct_events)
242*a71a9546SAutomerger Merge Worker 		ct_print_events("ctevents", ct_event_tbl,
243*a71a9546SAutomerger Merge Worker 				ARRAY_SIZE(ct_event_tbl), info->ct_events);
244*a71a9546SAutomerger Merge Worker 	if (info->exp_events)
245*a71a9546SAutomerger Merge Worker 		ct_print_events("expevents", exp_event_tbl,
246*a71a9546SAutomerger Merge Worker 				ARRAY_SIZE(exp_event_tbl), info->exp_events);
247*a71a9546SAutomerger Merge Worker 	if (info->flags & XT_CT_ZONE_MARK || info->zone)
248*a71a9546SAutomerger Merge Worker 		ct_print_zone_id("zone", info->zone, info->flags);
249*a71a9546SAutomerger Merge Worker }
250*a71a9546SAutomerger Merge Worker 
251*a71a9546SAutomerger Merge Worker static void
ct_print_v1(const void * ip,const struct xt_entry_target * target,int numeric)252*a71a9546SAutomerger Merge Worker ct_print_v1(const void *ip, const struct xt_entry_target *target, int numeric)
253*a71a9546SAutomerger Merge Worker {
254*a71a9546SAutomerger Merge Worker 	const struct xt_ct_target_info_v1 *info =
255*a71a9546SAutomerger Merge Worker 		(const struct xt_ct_target_info_v1 *)target->data;
256*a71a9546SAutomerger Merge Worker 
257*a71a9546SAutomerger Merge Worker 	if (info->flags & XT_CT_NOTRACK_ALIAS) {
258*a71a9546SAutomerger Merge Worker 		printf (" NOTRACK");
259*a71a9546SAutomerger Merge Worker 		return;
260*a71a9546SAutomerger Merge Worker 	}
261*a71a9546SAutomerger Merge Worker 	printf(" CT");
262*a71a9546SAutomerger Merge Worker 	if (info->flags & XT_CT_NOTRACK)
263*a71a9546SAutomerger Merge Worker 		printf(" notrack");
264*a71a9546SAutomerger Merge Worker 	if (info->helper[0])
265*a71a9546SAutomerger Merge Worker 		printf(" helper %s", info->helper);
266*a71a9546SAutomerger Merge Worker 	if (info->timeout[0])
267*a71a9546SAutomerger Merge Worker 		printf(" timeout %s", info->timeout);
268*a71a9546SAutomerger Merge Worker 	if (info->ct_events)
269*a71a9546SAutomerger Merge Worker 		ct_print_events("ctevents", ct_event_tbl,
270*a71a9546SAutomerger Merge Worker 				ARRAY_SIZE(ct_event_tbl), info->ct_events);
271*a71a9546SAutomerger Merge Worker 	if (info->exp_events)
272*a71a9546SAutomerger Merge Worker 		ct_print_events("expevents", exp_event_tbl,
273*a71a9546SAutomerger Merge Worker 				ARRAY_SIZE(exp_event_tbl), info->exp_events);
274*a71a9546SAutomerger Merge Worker 	if (info->flags & XT_CT_ZONE_MARK || info->zone)
275*a71a9546SAutomerger Merge Worker 		ct_print_zone_id("zone", info->zone, info->flags);
276*a71a9546SAutomerger Merge Worker }
277*a71a9546SAutomerger Merge Worker 
ct_save(const void * ip,const struct xt_entry_target * target)278*a71a9546SAutomerger Merge Worker static void ct_save(const void *ip, const struct xt_entry_target *target)
279*a71a9546SAutomerger Merge Worker {
280*a71a9546SAutomerger Merge Worker 	const struct xt_ct_target_info *info =
281*a71a9546SAutomerger Merge Worker 		(const struct xt_ct_target_info *)target->data;
282*a71a9546SAutomerger Merge Worker 
283*a71a9546SAutomerger Merge Worker 	if (info->flags & XT_CT_NOTRACK_ALIAS)
284*a71a9546SAutomerger Merge Worker 		return;
285*a71a9546SAutomerger Merge Worker 	if (info->flags & XT_CT_NOTRACK)
286*a71a9546SAutomerger Merge Worker 		printf(" --notrack");
287*a71a9546SAutomerger Merge Worker 	if (info->helper[0])
288*a71a9546SAutomerger Merge Worker 		printf(" --helper %s", info->helper);
289*a71a9546SAutomerger Merge Worker 	if (info->ct_events)
290*a71a9546SAutomerger Merge Worker 		ct_print_events("--ctevents", ct_event_tbl,
291*a71a9546SAutomerger Merge Worker 				ARRAY_SIZE(ct_event_tbl), info->ct_events);
292*a71a9546SAutomerger Merge Worker 	if (info->exp_events)
293*a71a9546SAutomerger Merge Worker 		ct_print_events("--expevents", exp_event_tbl,
294*a71a9546SAutomerger Merge Worker 				ARRAY_SIZE(exp_event_tbl), info->exp_events);
295*a71a9546SAutomerger Merge Worker 	if (info->flags & XT_CT_ZONE_MARK || info->zone)
296*a71a9546SAutomerger Merge Worker 		ct_print_zone_id("--zone", info->zone, info->flags);
297*a71a9546SAutomerger Merge Worker }
298*a71a9546SAutomerger Merge Worker 
ct_save_v1(const void * ip,const struct xt_entry_target * target)299*a71a9546SAutomerger Merge Worker static void ct_save_v1(const void *ip, const struct xt_entry_target *target)
300*a71a9546SAutomerger Merge Worker {
301*a71a9546SAutomerger Merge Worker 	const struct xt_ct_target_info_v1 *info =
302*a71a9546SAutomerger Merge Worker 		(const struct xt_ct_target_info_v1 *)target->data;
303*a71a9546SAutomerger Merge Worker 
304*a71a9546SAutomerger Merge Worker 	if (info->flags & XT_CT_NOTRACK_ALIAS)
305*a71a9546SAutomerger Merge Worker 		return;
306*a71a9546SAutomerger Merge Worker 	if (info->flags & XT_CT_NOTRACK)
307*a71a9546SAutomerger Merge Worker 		printf(" --notrack");
308*a71a9546SAutomerger Merge Worker 	if (info->helper[0])
309*a71a9546SAutomerger Merge Worker 		printf(" --helper %s", info->helper);
310*a71a9546SAutomerger Merge Worker 	if (info->timeout[0])
311*a71a9546SAutomerger Merge Worker 		printf(" --timeout %s", info->timeout);
312*a71a9546SAutomerger Merge Worker 	if (info->ct_events)
313*a71a9546SAutomerger Merge Worker 		ct_print_events("--ctevents", ct_event_tbl,
314*a71a9546SAutomerger Merge Worker 				ARRAY_SIZE(ct_event_tbl), info->ct_events);
315*a71a9546SAutomerger Merge Worker 	if (info->exp_events)
316*a71a9546SAutomerger Merge Worker 		ct_print_events("--expevents", exp_event_tbl,
317*a71a9546SAutomerger Merge Worker 				ARRAY_SIZE(exp_event_tbl), info->exp_events);
318*a71a9546SAutomerger Merge Worker 	if (info->flags & XT_CT_ZONE_MARK || info->zone)
319*a71a9546SAutomerger Merge Worker 		ct_print_zone_id("--zone", info->zone, info->flags);
320*a71a9546SAutomerger Merge Worker }
321*a71a9546SAutomerger Merge Worker 
322*a71a9546SAutomerger Merge Worker static const char *
ct_print_name_alias(const struct xt_entry_target * target)323*a71a9546SAutomerger Merge Worker ct_print_name_alias(const struct xt_entry_target *target)
324*a71a9546SAutomerger Merge Worker {
325*a71a9546SAutomerger Merge Worker 	struct xt_ct_target_info *info = (void *)target->data;
326*a71a9546SAutomerger Merge Worker 
327*a71a9546SAutomerger Merge Worker 	return info->flags & XT_CT_NOTRACK_ALIAS ? "NOTRACK" : "CT";
328*a71a9546SAutomerger Merge Worker }
329*a71a9546SAutomerger Merge Worker 
notrack_ct0_tg_init(struct xt_entry_target * target)330*a71a9546SAutomerger Merge Worker static void notrack_ct0_tg_init(struct xt_entry_target *target)
331*a71a9546SAutomerger Merge Worker {
332*a71a9546SAutomerger Merge Worker 	struct xt_ct_target_info *info = (void *)target->data;
333*a71a9546SAutomerger Merge Worker 
334*a71a9546SAutomerger Merge Worker 	info->flags = XT_CT_NOTRACK;
335*a71a9546SAutomerger Merge Worker }
336*a71a9546SAutomerger Merge Worker 
notrack_ct1_tg_init(struct xt_entry_target * target)337*a71a9546SAutomerger Merge Worker static void notrack_ct1_tg_init(struct xt_entry_target *target)
338*a71a9546SAutomerger Merge Worker {
339*a71a9546SAutomerger Merge Worker 	struct xt_ct_target_info_v1 *info = (void *)target->data;
340*a71a9546SAutomerger Merge Worker 
341*a71a9546SAutomerger Merge Worker 	info->flags = XT_CT_NOTRACK;
342*a71a9546SAutomerger Merge Worker }
343*a71a9546SAutomerger Merge Worker 
notrack_ct2_tg_init(struct xt_entry_target * target)344*a71a9546SAutomerger Merge Worker static void notrack_ct2_tg_init(struct xt_entry_target *target)
345*a71a9546SAutomerger Merge Worker {
346*a71a9546SAutomerger Merge Worker 	struct xt_ct_target_info_v1 *info = (void *)target->data;
347*a71a9546SAutomerger Merge Worker 
348*a71a9546SAutomerger Merge Worker 	info->flags = XT_CT_NOTRACK | XT_CT_NOTRACK_ALIAS;
349*a71a9546SAutomerger Merge Worker }
350*a71a9546SAutomerger Merge Worker 
xlate_ct1_tg(struct xt_xlate * xl,const struct xt_xlate_tg_params * params)351*a71a9546SAutomerger Merge Worker static int xlate_ct1_tg(struct xt_xlate *xl,
352*a71a9546SAutomerger Merge Worker 			const struct xt_xlate_tg_params *params)
353*a71a9546SAutomerger Merge Worker {
354*a71a9546SAutomerger Merge Worker 	struct xt_ct_target_info_v1 *info =
355*a71a9546SAutomerger Merge Worker 		(struct xt_ct_target_info_v1 *)params->target->data;
356*a71a9546SAutomerger Merge Worker 
357*a71a9546SAutomerger Merge Worker 	if (info->flags & XT_CT_NOTRACK)
358*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "notrack");
359*a71a9546SAutomerger Merge Worker 	else
360*a71a9546SAutomerger Merge Worker 		return 0;
361*a71a9546SAutomerger Merge Worker 
362*a71a9546SAutomerger Merge Worker 	return 1;
363*a71a9546SAutomerger Merge Worker }
364*a71a9546SAutomerger Merge Worker 
365*a71a9546SAutomerger Merge Worker static struct xtables_target ct_target_reg[] = {
366*a71a9546SAutomerger Merge Worker 	{
367*a71a9546SAutomerger Merge Worker 		.family		= NFPROTO_UNSPEC,
368*a71a9546SAutomerger Merge Worker 		.name		= "CT",
369*a71a9546SAutomerger Merge Worker 		.version	= XTABLES_VERSION,
370*a71a9546SAutomerger Merge Worker 		.size		= XT_ALIGN(sizeof(struct xt_ct_target_info)),
371*a71a9546SAutomerger Merge Worker 		.userspacesize	= offsetof(struct xt_ct_target_info, ct),
372*a71a9546SAutomerger Merge Worker 		.help		= ct_help,
373*a71a9546SAutomerger Merge Worker 		.print		= ct_print,
374*a71a9546SAutomerger Merge Worker 		.save		= ct_save,
375*a71a9546SAutomerger Merge Worker 		.x6_parse	= ct_parse,
376*a71a9546SAutomerger Merge Worker 		.x6_options	= ct_opts,
377*a71a9546SAutomerger Merge Worker 	},
378*a71a9546SAutomerger Merge Worker 	{
379*a71a9546SAutomerger Merge Worker 		.family		= NFPROTO_UNSPEC,
380*a71a9546SAutomerger Merge Worker 		.name		= "CT",
381*a71a9546SAutomerger Merge Worker 		.revision	= 1,
382*a71a9546SAutomerger Merge Worker 		.version	= XTABLES_VERSION,
383*a71a9546SAutomerger Merge Worker 		.size		= XT_ALIGN(sizeof(struct xt_ct_target_info_v1)),
384*a71a9546SAutomerger Merge Worker 		.userspacesize	= offsetof(struct xt_ct_target_info_v1, ct),
385*a71a9546SAutomerger Merge Worker 		.help		= ct_help_v1,
386*a71a9546SAutomerger Merge Worker 		.print		= ct_print_v1,
387*a71a9546SAutomerger Merge Worker 		.save		= ct_save_v1,
388*a71a9546SAutomerger Merge Worker 		.x6_parse	= ct_parse_v1,
389*a71a9546SAutomerger Merge Worker 		.x6_options	= ct_opts_v1,
390*a71a9546SAutomerger Merge Worker 	},
391*a71a9546SAutomerger Merge Worker 	{
392*a71a9546SAutomerger Merge Worker 		.family		= NFPROTO_UNSPEC,
393*a71a9546SAutomerger Merge Worker 		.name		= "CT",
394*a71a9546SAutomerger Merge Worker 		.revision	= 2,
395*a71a9546SAutomerger Merge Worker 		.version	= XTABLES_VERSION,
396*a71a9546SAutomerger Merge Worker 		.size		= XT_ALIGN(sizeof(struct xt_ct_target_info_v1)),
397*a71a9546SAutomerger Merge Worker 		.userspacesize	= offsetof(struct xt_ct_target_info_v1, ct),
398*a71a9546SAutomerger Merge Worker 		.help		= ct_help_v1,
399*a71a9546SAutomerger Merge Worker 		.print		= ct_print_v1,
400*a71a9546SAutomerger Merge Worker 		.save		= ct_save_v1,
401*a71a9546SAutomerger Merge Worker 		.alias		= ct_print_name_alias,
402*a71a9546SAutomerger Merge Worker 		.x6_parse	= ct_parse_v1,
403*a71a9546SAutomerger Merge Worker 		.x6_options	= ct_opts_v1,
404*a71a9546SAutomerger Merge Worker 		.xlate		= xlate_ct1_tg,
405*a71a9546SAutomerger Merge Worker 	},
406*a71a9546SAutomerger Merge Worker 	{
407*a71a9546SAutomerger Merge Worker 		.family        = NFPROTO_UNSPEC,
408*a71a9546SAutomerger Merge Worker 		.name          = "NOTRACK",
409*a71a9546SAutomerger Merge Worker 		.real_name     = "CT",
410*a71a9546SAutomerger Merge Worker 		.revision      = 0,
411*a71a9546SAutomerger Merge Worker 		.version       = XTABLES_VERSION,
412*a71a9546SAutomerger Merge Worker 		.size          = XT_ALIGN(sizeof(struct xt_ct_target_info)),
413*a71a9546SAutomerger Merge Worker 		.userspacesize = offsetof(struct xt_ct_target_info, ct),
414*a71a9546SAutomerger Merge Worker 		.init          = notrack_ct0_tg_init,
415*a71a9546SAutomerger Merge Worker 	},
416*a71a9546SAutomerger Merge Worker 	{
417*a71a9546SAutomerger Merge Worker 		.family        = NFPROTO_UNSPEC,
418*a71a9546SAutomerger Merge Worker 		.name          = "NOTRACK",
419*a71a9546SAutomerger Merge Worker 		.real_name     = "CT",
420*a71a9546SAutomerger Merge Worker 		.revision      = 1,
421*a71a9546SAutomerger Merge Worker 		.version       = XTABLES_VERSION,
422*a71a9546SAutomerger Merge Worker 		.size          = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)),
423*a71a9546SAutomerger Merge Worker 		.userspacesize = offsetof(struct xt_ct_target_info_v1, ct),
424*a71a9546SAutomerger Merge Worker 		.init          = notrack_ct1_tg_init,
425*a71a9546SAutomerger Merge Worker 	},
426*a71a9546SAutomerger Merge Worker 	{
427*a71a9546SAutomerger Merge Worker 		.family        = NFPROTO_UNSPEC,
428*a71a9546SAutomerger Merge Worker 		.name          = "NOTRACK",
429*a71a9546SAutomerger Merge Worker 		.real_name     = "CT",
430*a71a9546SAutomerger Merge Worker 		.revision      = 2,
431*a71a9546SAutomerger Merge Worker 		.ext_flags     = XTABLES_EXT_ALIAS,
432*a71a9546SAutomerger Merge Worker 		.version       = XTABLES_VERSION,
433*a71a9546SAutomerger Merge Worker 		.size          = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)),
434*a71a9546SAutomerger Merge Worker 		.userspacesize = offsetof(struct xt_ct_target_info_v1, ct),
435*a71a9546SAutomerger Merge Worker 		.init          = notrack_ct2_tg_init,
436*a71a9546SAutomerger Merge Worker 		.xlate	       = xlate_ct1_tg,
437*a71a9546SAutomerger Merge Worker 	},
438*a71a9546SAutomerger Merge Worker 	{
439*a71a9546SAutomerger Merge Worker 		.family        = NFPROTO_UNSPEC,
440*a71a9546SAutomerger Merge Worker 		.name          = "NOTRACK",
441*a71a9546SAutomerger Merge Worker 		.revision      = 0,
442*a71a9546SAutomerger Merge Worker 		.version       = XTABLES_VERSION,
443*a71a9546SAutomerger Merge Worker 	},
444*a71a9546SAutomerger Merge Worker };
445*a71a9546SAutomerger Merge Worker 
_init(void)446*a71a9546SAutomerger Merge Worker void _init(void)
447*a71a9546SAutomerger Merge Worker {
448*a71a9546SAutomerger Merge Worker 	xtables_register_targets(ct_target_reg, ARRAY_SIZE(ct_target_reg));
449*a71a9546SAutomerger Merge Worker }
450