xref: /aosp_15_r20/external/iptables/extensions/libxt_dccp.c (revision a71a954618bbadd4a345637e5edcf36eec826889)
1*a71a9546SAutomerger Merge Worker /* Shared library add-on to iptables for DCCP matching
2*a71a9546SAutomerger Merge Worker  *
3*a71a9546SAutomerger Merge Worker  * (C) 2005 by Harald Welte <[email protected]>
4*a71a9546SAutomerger Merge Worker  *
5*a71a9546SAutomerger Merge Worker  * This program is distributed under the terms of GNU GPL v2, 1991
6*a71a9546SAutomerger Merge Worker  *
7*a71a9546SAutomerger Merge Worker  */
8*a71a9546SAutomerger Merge Worker #include <stdint.h>
9*a71a9546SAutomerger Merge Worker #include <stdio.h>
10*a71a9546SAutomerger Merge Worker #include <string.h>
11*a71a9546SAutomerger Merge Worker #include <stdlib.h>
12*a71a9546SAutomerger Merge Worker #include <netdb.h>
13*a71a9546SAutomerger Merge Worker #include <arpa/inet.h>
14*a71a9546SAutomerger Merge Worker #include <xtables.h>
15*a71a9546SAutomerger Merge Worker #include <linux/dccp.h>
16*a71a9546SAutomerger Merge Worker #include <linux/netfilter/x_tables.h>
17*a71a9546SAutomerger Merge Worker #include <linux/netfilter/xt_dccp.h>
18*a71a9546SAutomerger Merge Worker 
19*a71a9546SAutomerger Merge Worker #if 0
20*a71a9546SAutomerger Merge Worker #define DEBUGP(format, first...) printf(format, ##first)
21*a71a9546SAutomerger Merge Worker #define static
22*a71a9546SAutomerger Merge Worker #else
23*a71a9546SAutomerger Merge Worker #define DEBUGP(format, fist...)
24*a71a9546SAutomerger Merge Worker #endif
25*a71a9546SAutomerger Merge Worker 
26*a71a9546SAutomerger Merge Worker enum {
27*a71a9546SAutomerger Merge Worker 	O_SOURCE_PORT = 0,
28*a71a9546SAutomerger Merge Worker 	O_DEST_PORT,
29*a71a9546SAutomerger Merge Worker 	O_DCCP_TYPES,
30*a71a9546SAutomerger Merge Worker 	O_DCCP_OPTION,
31*a71a9546SAutomerger Merge Worker };
32*a71a9546SAutomerger Merge Worker 
dccp_help(void)33*a71a9546SAutomerger Merge Worker static void dccp_help(void)
34*a71a9546SAutomerger Merge Worker {
35*a71a9546SAutomerger Merge Worker 	printf(
36*a71a9546SAutomerger Merge Worker "dccp match options\n"
37*a71a9546SAutomerger Merge Worker "[!] --source-port port[:port]                          match source port(s)\n"
38*a71a9546SAutomerger Merge Worker " --sport ...\n"
39*a71a9546SAutomerger Merge Worker "[!] --destination-port port[:port]                     match destination port(s)\n"
40*a71a9546SAutomerger Merge Worker " --dport ...\n"
41*a71a9546SAutomerger Merge Worker "[!] --dccp-types type[,...]                            match when packet is one of the given types\n"
42*a71a9546SAutomerger Merge Worker "[!] --dccp-option option                               match if option (by number!) is set\n"
43*a71a9546SAutomerger Merge Worker );
44*a71a9546SAutomerger Merge Worker }
45*a71a9546SAutomerger Merge Worker 
46*a71a9546SAutomerger Merge Worker #define s struct xt_dccp_info
47*a71a9546SAutomerger Merge Worker static const struct xt_option_entry dccp_opts[] = {
48*a71a9546SAutomerger Merge Worker 	{.name = "source-port", .id = O_SOURCE_PORT, .type = XTTYPE_PORTRC,
49*a71a9546SAutomerger Merge Worker 	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spts)},
50*a71a9546SAutomerger Merge Worker 	{.name = "sport", .id = O_SOURCE_PORT, .type = XTTYPE_PORTRC,
51*a71a9546SAutomerger Merge Worker 	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spts)},
52*a71a9546SAutomerger Merge Worker 	{.name = "destination-port", .id = O_DEST_PORT, .type = XTTYPE_PORTRC,
53*a71a9546SAutomerger Merge Worker 	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, dpts)},
54*a71a9546SAutomerger Merge Worker 	{.name = "dport", .id = O_DEST_PORT, .type = XTTYPE_PORTRC,
55*a71a9546SAutomerger Merge Worker 	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, dpts)},
56*a71a9546SAutomerger Merge Worker 	{.name = "dccp-types", .id = O_DCCP_TYPES, .type = XTTYPE_STRING,
57*a71a9546SAutomerger Merge Worker 	 .flags = XTOPT_INVERT},
58*a71a9546SAutomerger Merge Worker 	{.name = "dccp-option", .id = O_DCCP_OPTION, .type = XTTYPE_UINT8,
59*a71a9546SAutomerger Merge Worker 	 .min = 1, .max = UINT8_MAX, .flags = XTOPT_INVERT | XTOPT_PUT,
60*a71a9546SAutomerger Merge Worker 	 XTOPT_POINTER(s, option)},
61*a71a9546SAutomerger Merge Worker 	XTOPT_TABLEEND,
62*a71a9546SAutomerger Merge Worker };
63*a71a9546SAutomerger Merge Worker #undef s
64*a71a9546SAutomerger Merge Worker 
65*a71a9546SAutomerger Merge Worker static const char *const dccp_pkt_types[] = {
66*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_REQUEST] 	= "REQUEST",
67*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_RESPONSE]	= "RESPONSE",
68*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_DATA]		= "DATA",
69*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_ACK]		= "ACK",
70*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_DATAACK]	= "DATAACK",
71*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_CLOSEREQ]	= "CLOSEREQ",
72*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_CLOSE]	= "CLOSE",
73*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_RESET]	= "RESET",
74*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_SYNC]		= "SYNC",
75*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_SYNCACK]	= "SYNCACK",
76*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_INVALID]	= "INVALID",
77*a71a9546SAutomerger Merge Worker };
78*a71a9546SAutomerger Merge Worker 
79*a71a9546SAutomerger Merge Worker /* Bits for type values 11-15 */
80*a71a9546SAutomerger Merge Worker #define INVALID_OTHER_TYPE_MASK		0xf800
81*a71a9546SAutomerger Merge Worker 
82*a71a9546SAutomerger Merge Worker static uint16_t
parse_dccp_types(const char * typestring)83*a71a9546SAutomerger Merge Worker parse_dccp_types(const char *typestring)
84*a71a9546SAutomerger Merge Worker {
85*a71a9546SAutomerger Merge Worker 	uint16_t typemask = 0;
86*a71a9546SAutomerger Merge Worker 	char *ptr, *buffer;
87*a71a9546SAutomerger Merge Worker 
88*a71a9546SAutomerger Merge Worker 	buffer = xtables_strdup(typestring);
89*a71a9546SAutomerger Merge Worker 
90*a71a9546SAutomerger Merge Worker 	for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
91*a71a9546SAutomerger Merge Worker 		unsigned int i;
92*a71a9546SAutomerger Merge Worker 		for (i = 0; i < ARRAY_SIZE(dccp_pkt_types); ++i)
93*a71a9546SAutomerger Merge Worker 			if (!strcasecmp(dccp_pkt_types[i], ptr)) {
94*a71a9546SAutomerger Merge Worker 				typemask |= (1 << i);
95*a71a9546SAutomerger Merge Worker 				break;
96*a71a9546SAutomerger Merge Worker 			}
97*a71a9546SAutomerger Merge Worker 		if (i == ARRAY_SIZE(dccp_pkt_types))
98*a71a9546SAutomerger Merge Worker 			xtables_error(PARAMETER_PROBLEM,
99*a71a9546SAutomerger Merge Worker 				   "Unknown DCCP type `%s'", ptr);
100*a71a9546SAutomerger Merge Worker 	}
101*a71a9546SAutomerger Merge Worker 	if (typemask & (1 << DCCP_PKT_INVALID))
102*a71a9546SAutomerger Merge Worker 		typemask |= INVALID_OTHER_TYPE_MASK;
103*a71a9546SAutomerger Merge Worker 
104*a71a9546SAutomerger Merge Worker 
105*a71a9546SAutomerger Merge Worker 	free(buffer);
106*a71a9546SAutomerger Merge Worker 	return typemask;
107*a71a9546SAutomerger Merge Worker }
108*a71a9546SAutomerger Merge Worker 
dccp_parse(struct xt_option_call * cb)109*a71a9546SAutomerger Merge Worker static void dccp_parse(struct xt_option_call *cb)
110*a71a9546SAutomerger Merge Worker {
111*a71a9546SAutomerger Merge Worker 	struct xt_dccp_info *einfo = cb->data;
112*a71a9546SAutomerger Merge Worker 
113*a71a9546SAutomerger Merge Worker 	xtables_option_parse(cb);
114*a71a9546SAutomerger Merge Worker 	switch (cb->entry->id) {
115*a71a9546SAutomerger Merge Worker 	case O_SOURCE_PORT:
116*a71a9546SAutomerger Merge Worker 		einfo->flags |= XT_DCCP_SRC_PORTS;
117*a71a9546SAutomerger Merge Worker 		if (cb->invert)
118*a71a9546SAutomerger Merge Worker 			einfo->invflags |= XT_DCCP_SRC_PORTS;
119*a71a9546SAutomerger Merge Worker 		break;
120*a71a9546SAutomerger Merge Worker 	case O_DEST_PORT:
121*a71a9546SAutomerger Merge Worker 		einfo->flags |= XT_DCCP_DEST_PORTS;
122*a71a9546SAutomerger Merge Worker 		if (cb->invert)
123*a71a9546SAutomerger Merge Worker 			einfo->invflags |= XT_DCCP_DEST_PORTS;
124*a71a9546SAutomerger Merge Worker 		break;
125*a71a9546SAutomerger Merge Worker 	case O_DCCP_TYPES:
126*a71a9546SAutomerger Merge Worker 		einfo->flags |= XT_DCCP_TYPE;
127*a71a9546SAutomerger Merge Worker 		einfo->typemask = parse_dccp_types(cb->arg);
128*a71a9546SAutomerger Merge Worker 		if (cb->invert)
129*a71a9546SAutomerger Merge Worker 			einfo->invflags |= XT_DCCP_TYPE;
130*a71a9546SAutomerger Merge Worker 		break;
131*a71a9546SAutomerger Merge Worker 	case O_DCCP_OPTION:
132*a71a9546SAutomerger Merge Worker 		einfo->flags |= XT_DCCP_OPTION;
133*a71a9546SAutomerger Merge Worker 		if (cb->invert)
134*a71a9546SAutomerger Merge Worker 			einfo->invflags |= XT_DCCP_OPTION;
135*a71a9546SAutomerger Merge Worker 		break;
136*a71a9546SAutomerger Merge Worker 	}
137*a71a9546SAutomerger Merge Worker }
138*a71a9546SAutomerger Merge Worker 
139*a71a9546SAutomerger Merge Worker static const char *
port_to_service(int port)140*a71a9546SAutomerger Merge Worker port_to_service(int port)
141*a71a9546SAutomerger Merge Worker {
142*a71a9546SAutomerger Merge Worker 	const struct servent *service;
143*a71a9546SAutomerger Merge Worker 
144*a71a9546SAutomerger Merge Worker 	if ((service = getservbyport(htons(port), "dccp")))
145*a71a9546SAutomerger Merge Worker 		return service->s_name;
146*a71a9546SAutomerger Merge Worker 
147*a71a9546SAutomerger Merge Worker 	return NULL;
148*a71a9546SAutomerger Merge Worker }
149*a71a9546SAutomerger Merge Worker 
150*a71a9546SAutomerger Merge Worker static void
print_port(uint16_t port,int numeric)151*a71a9546SAutomerger Merge Worker print_port(uint16_t port, int numeric)
152*a71a9546SAutomerger Merge Worker {
153*a71a9546SAutomerger Merge Worker 	const char *service;
154*a71a9546SAutomerger Merge Worker 
155*a71a9546SAutomerger Merge Worker 	if (numeric || (service = port_to_service(port)) == NULL)
156*a71a9546SAutomerger Merge Worker 		printf("%u", port);
157*a71a9546SAutomerger Merge Worker 	else
158*a71a9546SAutomerger Merge Worker 		printf("%s", service);
159*a71a9546SAutomerger Merge Worker }
160*a71a9546SAutomerger Merge Worker 
161*a71a9546SAutomerger Merge Worker static void
print_ports(const char * name,uint16_t min,uint16_t max,int invert,int numeric)162*a71a9546SAutomerger Merge Worker print_ports(const char *name, uint16_t min, uint16_t max,
163*a71a9546SAutomerger Merge Worker 	    int invert, int numeric)
164*a71a9546SAutomerger Merge Worker {
165*a71a9546SAutomerger Merge Worker 	const char *inv = invert ? "!" : "";
166*a71a9546SAutomerger Merge Worker 
167*a71a9546SAutomerger Merge Worker 	if (min != 0 || max != 0xFFFF || invert) {
168*a71a9546SAutomerger Merge Worker 		printf(" %s", name);
169*a71a9546SAutomerger Merge Worker 		if (min == max) {
170*a71a9546SAutomerger Merge Worker 			printf(":%s", inv);
171*a71a9546SAutomerger Merge Worker 			print_port(min, numeric);
172*a71a9546SAutomerger Merge Worker 		} else {
173*a71a9546SAutomerger Merge Worker 			printf("s:%s", inv);
174*a71a9546SAutomerger Merge Worker 			print_port(min, numeric);
175*a71a9546SAutomerger Merge Worker 			printf(":");
176*a71a9546SAutomerger Merge Worker 			print_port(max, numeric);
177*a71a9546SAutomerger Merge Worker 		}
178*a71a9546SAutomerger Merge Worker 	}
179*a71a9546SAutomerger Merge Worker }
180*a71a9546SAutomerger Merge Worker 
181*a71a9546SAutomerger Merge Worker static void
print_types(uint16_t types,int inverted,int numeric)182*a71a9546SAutomerger Merge Worker print_types(uint16_t types, int inverted, int numeric)
183*a71a9546SAutomerger Merge Worker {
184*a71a9546SAutomerger Merge Worker 	int have_type = 0;
185*a71a9546SAutomerger Merge Worker 
186*a71a9546SAutomerger Merge Worker 	if (inverted)
187*a71a9546SAutomerger Merge Worker 		printf(" !");
188*a71a9546SAutomerger Merge Worker 
189*a71a9546SAutomerger Merge Worker 	printf(" ");
190*a71a9546SAutomerger Merge Worker 	while (types) {
191*a71a9546SAutomerger Merge Worker 		unsigned int i;
192*a71a9546SAutomerger Merge Worker 
193*a71a9546SAutomerger Merge Worker 		for (i = 0; !(types & (1 << i)); i++);
194*a71a9546SAutomerger Merge Worker 
195*a71a9546SAutomerger Merge Worker 		if (have_type)
196*a71a9546SAutomerger Merge Worker 			printf(",");
197*a71a9546SAutomerger Merge Worker 		else
198*a71a9546SAutomerger Merge Worker 			have_type = 1;
199*a71a9546SAutomerger Merge Worker 
200*a71a9546SAutomerger Merge Worker 		if (numeric)
201*a71a9546SAutomerger Merge Worker 			printf("%u", i);
202*a71a9546SAutomerger Merge Worker 		else {
203*a71a9546SAutomerger Merge Worker 			printf("%s", dccp_pkt_types[i]);
204*a71a9546SAutomerger Merge Worker 
205*a71a9546SAutomerger Merge Worker 			if (i == DCCP_PKT_INVALID)
206*a71a9546SAutomerger Merge Worker 				break;
207*a71a9546SAutomerger Merge Worker 		}
208*a71a9546SAutomerger Merge Worker 
209*a71a9546SAutomerger Merge Worker 		types &= ~(1 << i);
210*a71a9546SAutomerger Merge Worker 	}
211*a71a9546SAutomerger Merge Worker }
212*a71a9546SAutomerger Merge Worker 
213*a71a9546SAutomerger Merge Worker static void
print_option(uint8_t option,int invert,int numeric)214*a71a9546SAutomerger Merge Worker print_option(uint8_t option, int invert, int numeric)
215*a71a9546SAutomerger Merge Worker {
216*a71a9546SAutomerger Merge Worker 	if (option || invert)
217*a71a9546SAutomerger Merge Worker 		printf(" option=%s%u", invert ? "!" : "", option);
218*a71a9546SAutomerger Merge Worker }
219*a71a9546SAutomerger Merge Worker 
220*a71a9546SAutomerger Merge Worker static void
dccp_print(const void * ip,const struct xt_entry_match * match,int numeric)221*a71a9546SAutomerger Merge Worker dccp_print(const void *ip, const struct xt_entry_match *match, int numeric)
222*a71a9546SAutomerger Merge Worker {
223*a71a9546SAutomerger Merge Worker 	const struct xt_dccp_info *einfo =
224*a71a9546SAutomerger Merge Worker 		(const struct xt_dccp_info *)match->data;
225*a71a9546SAutomerger Merge Worker 
226*a71a9546SAutomerger Merge Worker 	printf(" dccp");
227*a71a9546SAutomerger Merge Worker 
228*a71a9546SAutomerger Merge Worker 	if (einfo->flags & XT_DCCP_SRC_PORTS) {
229*a71a9546SAutomerger Merge Worker 		print_ports("spt", einfo->spts[0], einfo->spts[1],
230*a71a9546SAutomerger Merge Worker 			einfo->invflags & XT_DCCP_SRC_PORTS,
231*a71a9546SAutomerger Merge Worker 			numeric);
232*a71a9546SAutomerger Merge Worker 	}
233*a71a9546SAutomerger Merge Worker 
234*a71a9546SAutomerger Merge Worker 	if (einfo->flags & XT_DCCP_DEST_PORTS) {
235*a71a9546SAutomerger Merge Worker 		print_ports("dpt", einfo->dpts[0], einfo->dpts[1],
236*a71a9546SAutomerger Merge Worker 			einfo->invflags & XT_DCCP_DEST_PORTS,
237*a71a9546SAutomerger Merge Worker 			numeric);
238*a71a9546SAutomerger Merge Worker 	}
239*a71a9546SAutomerger Merge Worker 
240*a71a9546SAutomerger Merge Worker 	if (einfo->flags & XT_DCCP_TYPE) {
241*a71a9546SAutomerger Merge Worker 		print_types(einfo->typemask,
242*a71a9546SAutomerger Merge Worker 			   einfo->invflags & XT_DCCP_TYPE,
243*a71a9546SAutomerger Merge Worker 			   numeric);
244*a71a9546SAutomerger Merge Worker 	}
245*a71a9546SAutomerger Merge Worker 
246*a71a9546SAutomerger Merge Worker 	if (einfo->flags & XT_DCCP_OPTION) {
247*a71a9546SAutomerger Merge Worker 		print_option(einfo->option,
248*a71a9546SAutomerger Merge Worker 			     einfo->invflags & XT_DCCP_OPTION, numeric);
249*a71a9546SAutomerger Merge Worker 	}
250*a71a9546SAutomerger Merge Worker }
251*a71a9546SAutomerger Merge Worker 
dccp_save(const void * ip,const struct xt_entry_match * match)252*a71a9546SAutomerger Merge Worker static void dccp_save(const void *ip, const struct xt_entry_match *match)
253*a71a9546SAutomerger Merge Worker {
254*a71a9546SAutomerger Merge Worker 	const struct xt_dccp_info *einfo =
255*a71a9546SAutomerger Merge Worker 		(const struct xt_dccp_info *)match->data;
256*a71a9546SAutomerger Merge Worker 
257*a71a9546SAutomerger Merge Worker 	if (einfo->flags & XT_DCCP_SRC_PORTS) {
258*a71a9546SAutomerger Merge Worker 		if (einfo->invflags & XT_DCCP_SRC_PORTS)
259*a71a9546SAutomerger Merge Worker 			printf(" !");
260*a71a9546SAutomerger Merge Worker 		if (einfo->spts[0] != einfo->spts[1])
261*a71a9546SAutomerger Merge Worker 			printf(" --sport %u:%u",
262*a71a9546SAutomerger Merge Worker 			       einfo->spts[0], einfo->spts[1]);
263*a71a9546SAutomerger Merge Worker 		else
264*a71a9546SAutomerger Merge Worker 			printf(" --sport %u", einfo->spts[0]);
265*a71a9546SAutomerger Merge Worker 	}
266*a71a9546SAutomerger Merge Worker 
267*a71a9546SAutomerger Merge Worker 	if (einfo->flags & XT_DCCP_DEST_PORTS) {
268*a71a9546SAutomerger Merge Worker 		if (einfo->invflags & XT_DCCP_DEST_PORTS)
269*a71a9546SAutomerger Merge Worker 			printf(" !");
270*a71a9546SAutomerger Merge Worker 		if (einfo->dpts[0] != einfo->dpts[1])
271*a71a9546SAutomerger Merge Worker 			printf(" --dport %u:%u",
272*a71a9546SAutomerger Merge Worker 			       einfo->dpts[0], einfo->dpts[1]);
273*a71a9546SAutomerger Merge Worker 		else
274*a71a9546SAutomerger Merge Worker 			printf(" --dport %u", einfo->dpts[0]);
275*a71a9546SAutomerger Merge Worker 	}
276*a71a9546SAutomerger Merge Worker 
277*a71a9546SAutomerger Merge Worker 	if (einfo->flags & XT_DCCP_TYPE) {
278*a71a9546SAutomerger Merge Worker 		printf("%s --dccp-types",
279*a71a9546SAutomerger Merge Worker 		       einfo->invflags & XT_DCCP_TYPE ? " !" : "");
280*a71a9546SAutomerger Merge Worker 		print_types(einfo->typemask, false, 0);
281*a71a9546SAutomerger Merge Worker 	}
282*a71a9546SAutomerger Merge Worker 
283*a71a9546SAutomerger Merge Worker 	if (einfo->flags & XT_DCCP_OPTION) {
284*a71a9546SAutomerger Merge Worker 		printf("%s --dccp-option %u",
285*a71a9546SAutomerger Merge Worker 			einfo->invflags & XT_DCCP_OPTION ? " !" : "",
286*a71a9546SAutomerger Merge Worker 			einfo->option);
287*a71a9546SAutomerger Merge Worker 	}
288*a71a9546SAutomerger Merge Worker }
289*a71a9546SAutomerger Merge Worker 
290*a71a9546SAutomerger Merge Worker static const char *const dccp_pkt_types_xlate[] = {
291*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_REQUEST]      = "request",
292*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_RESPONSE]     = "response",
293*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_DATA]         = "data",
294*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_ACK]          = "ack",
295*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_DATAACK]      = "dataack",
296*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_CLOSEREQ]     = "closereq",
297*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_CLOSE]        = "close",
298*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_RESET]        = "reset",
299*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_SYNC]         = "sync",
300*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_SYNCACK]      = "syncack",
301*a71a9546SAutomerger Merge Worker 	[DCCP_PKT_INVALID]	= "10-15",
302*a71a9546SAutomerger Merge Worker };
303*a71a9546SAutomerger Merge Worker 
dccp_type_xlate(const struct xt_dccp_info * einfo,struct xt_xlate * xl)304*a71a9546SAutomerger Merge Worker static int dccp_type_xlate(const struct xt_dccp_info *einfo,
305*a71a9546SAutomerger Merge Worker 			   struct xt_xlate *xl)
306*a71a9546SAutomerger Merge Worker {
307*a71a9546SAutomerger Merge Worker 	bool have_type = false, set_need = false;
308*a71a9546SAutomerger Merge Worker 	uint16_t types = einfo->typemask;
309*a71a9546SAutomerger Merge Worker 
310*a71a9546SAutomerger Merge Worker 	if (types & INVALID_OTHER_TYPE_MASK) {
311*a71a9546SAutomerger Merge Worker 		types &= ~INVALID_OTHER_TYPE_MASK;
312*a71a9546SAutomerger Merge Worker 		types |= 1 << DCCP_PKT_INVALID;
313*a71a9546SAutomerger Merge Worker 	}
314*a71a9546SAutomerger Merge Worker 
315*a71a9546SAutomerger Merge Worker 	if ((types != 0) && !(types == (types & -types))) {
316*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "{");
317*a71a9546SAutomerger Merge Worker 		set_need = true;
318*a71a9546SAutomerger Merge Worker 	}
319*a71a9546SAutomerger Merge Worker 
320*a71a9546SAutomerger Merge Worker 	while (types) {
321*a71a9546SAutomerger Merge Worker 		unsigned int i;
322*a71a9546SAutomerger Merge Worker 
323*a71a9546SAutomerger Merge Worker 		for (i = 0; !(types & (1 << i)); i++);
324*a71a9546SAutomerger Merge Worker 
325*a71a9546SAutomerger Merge Worker 		if (have_type)
326*a71a9546SAutomerger Merge Worker 			xt_xlate_add(xl, ", ");
327*a71a9546SAutomerger Merge Worker 		else
328*a71a9546SAutomerger Merge Worker 			have_type = true;
329*a71a9546SAutomerger Merge Worker 
330*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "%s", dccp_pkt_types_xlate[i]);
331*a71a9546SAutomerger Merge Worker 
332*a71a9546SAutomerger Merge Worker 		types &= ~(1 << i);
333*a71a9546SAutomerger Merge Worker 	}
334*a71a9546SAutomerger Merge Worker 
335*a71a9546SAutomerger Merge Worker 	if (set_need)
336*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "}");
337*a71a9546SAutomerger Merge Worker 
338*a71a9546SAutomerger Merge Worker 	return 1;
339*a71a9546SAutomerger Merge Worker }
340*a71a9546SAutomerger Merge Worker 
dccp_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)341*a71a9546SAutomerger Merge Worker static int dccp_xlate(struct xt_xlate *xl,
342*a71a9546SAutomerger Merge Worker 		      const struct xt_xlate_mt_params *params)
343*a71a9546SAutomerger Merge Worker {
344*a71a9546SAutomerger Merge Worker 	const struct xt_dccp_info *einfo =
345*a71a9546SAutomerger Merge Worker 		(const struct xt_dccp_info *)params->match->data;
346*a71a9546SAutomerger Merge Worker 	int ret = 1;
347*a71a9546SAutomerger Merge Worker 
348*a71a9546SAutomerger Merge Worker 	if (einfo->flags & XT_DCCP_SRC_PORTS) {
349*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "dccp sport%s %u",
350*a71a9546SAutomerger Merge Worker 			     einfo->invflags & XT_DCCP_SRC_PORTS ? " !=" : "",
351*a71a9546SAutomerger Merge Worker 			     einfo->spts[0]);
352*a71a9546SAutomerger Merge Worker 
353*a71a9546SAutomerger Merge Worker 		if (einfo->spts[0] != einfo->spts[1])
354*a71a9546SAutomerger Merge Worker 			xt_xlate_add(xl, "-%u", einfo->spts[1]);
355*a71a9546SAutomerger Merge Worker 	}
356*a71a9546SAutomerger Merge Worker 
357*a71a9546SAutomerger Merge Worker 	if (einfo->flags & XT_DCCP_DEST_PORTS) {
358*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "dccp dport%s %u",
359*a71a9546SAutomerger Merge Worker 			     einfo->invflags & XT_DCCP_DEST_PORTS ? " !=" : "",
360*a71a9546SAutomerger Merge Worker 			     einfo->dpts[0]);
361*a71a9546SAutomerger Merge Worker 
362*a71a9546SAutomerger Merge Worker 		if (einfo->dpts[0] != einfo->dpts[1])
363*a71a9546SAutomerger Merge Worker 			xt_xlate_add(xl, "-%u", einfo->dpts[1]);
364*a71a9546SAutomerger Merge Worker 	}
365*a71a9546SAutomerger Merge Worker 
366*a71a9546SAutomerger Merge Worker 	if (einfo->flags & XT_DCCP_TYPE && einfo->typemask) {
367*a71a9546SAutomerger Merge Worker 		xt_xlate_add(xl, "dccp type%s ",
368*a71a9546SAutomerger Merge Worker 			     einfo->invflags & XT_DCCP_TYPE ? " !=" : "");
369*a71a9546SAutomerger Merge Worker 		ret = dccp_type_xlate(einfo, xl);
370*a71a9546SAutomerger Merge Worker 	}
371*a71a9546SAutomerger Merge Worker 
372*a71a9546SAutomerger Merge Worker 	/* FIXME: no dccp option support in nftables yet */
373*a71a9546SAutomerger Merge Worker 	if (einfo->flags & XT_DCCP_OPTION)
374*a71a9546SAutomerger Merge Worker 		ret = 0;
375*a71a9546SAutomerger Merge Worker 
376*a71a9546SAutomerger Merge Worker 	return ret;
377*a71a9546SAutomerger Merge Worker }
378*a71a9546SAutomerger Merge Worker static struct xtables_match dccp_match = {
379*a71a9546SAutomerger Merge Worker 	.name		= "dccp",
380*a71a9546SAutomerger Merge Worker 	.family		= NFPROTO_UNSPEC,
381*a71a9546SAutomerger Merge Worker 	.version	= XTABLES_VERSION,
382*a71a9546SAutomerger Merge Worker 	.size		= XT_ALIGN(sizeof(struct xt_dccp_info)),
383*a71a9546SAutomerger Merge Worker 	.userspacesize	= XT_ALIGN(sizeof(struct xt_dccp_info)),
384*a71a9546SAutomerger Merge Worker 	.help		= dccp_help,
385*a71a9546SAutomerger Merge Worker 	.print		= dccp_print,
386*a71a9546SAutomerger Merge Worker 	.save		= dccp_save,
387*a71a9546SAutomerger Merge Worker 	.x6_parse	= dccp_parse,
388*a71a9546SAutomerger Merge Worker 	.x6_options	= dccp_opts,
389*a71a9546SAutomerger Merge Worker 	.xlate		= dccp_xlate,
390*a71a9546SAutomerger Merge Worker };
391*a71a9546SAutomerger Merge Worker 
_init(void)392*a71a9546SAutomerger Merge Worker void _init(void)
393*a71a9546SAutomerger Merge Worker {
394*a71a9546SAutomerger Merge Worker 	xtables_register_match(&dccp_match);
395*a71a9546SAutomerger Merge Worker }
396