blob: 28c59b9d95a223beb9ae33ef95a4c27f3a39f1c6 [file] [log] [blame]
Harald Weltee40b11d2005-08-06 21:13:04 +00001/* Shared library add-on to iptables for DCCP matching
2 *
3 * (C) 2005 by Harald Welte <laforge@netfilter.org>
4 *
5 * This program is distributed under the terms of GNU GPL v2, 1991
6 *
7 */
Jan Engelhardt753bbed2011-04-20 10:17:33 +02008#include <stdint.h>
Harald Weltee40b11d2005-08-06 21:13:04 +00009#include <stdio.h>
10#include <string.h>
11#include <stdlib.h>
Harald Weltee40b11d2005-08-06 21:13:04 +000012#include <netdb.h>
Jan Engelhardt753bbed2011-04-20 10:17:33 +020013#include <arpa/inet.h>
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +000014#include <xtables.h>
Harald Weltee40b11d2005-08-06 21:13:04 +000015#include <linux/dccp.h>
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +000016#include <linux/netfilter/x_tables.h>
17#include <linux/netfilter/xt_dccp.h>
Harald Weltee40b11d2005-08-06 21:13:04 +000018
19#if 0
20#define DEBUGP(format, first...) printf(format, ##first)
21#define static
22#else
23#define DEBUGP(format, fist...)
24#endif
25
Jan Engelhardt753bbed2011-04-20 10:17:33 +020026enum {
27 O_SOURCE_PORT = 0,
28 O_DEST_PORT,
29 O_DCCP_TYPES,
30 O_DCCP_OPTION,
31};
32
Jan Engelhardt181dead2007-10-04 16:27:07 +000033static void dccp_help(void)
Harald Weltee40b11d2005-08-06 21:13:04 +000034{
35 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020036"dccp match options\n"
Jan Engelhardt96727922008-08-13 14:42:41 +020037"[!] --source-port port[:port] match source port(s)\n"
Harald Weltee40b11d2005-08-06 21:13:04 +000038" --sport ...\n"
Jan Engelhardt96727922008-08-13 14:42:41 +020039"[!] --destination-port port[:port] match destination port(s)\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020040" --dport ...\n");
Harald Weltee40b11d2005-08-06 21:13:04 +000041}
42
Jan Engelhardt753bbed2011-04-20 10:17:33 +020043#define s struct xt_dccp_info
44static const struct xt_option_entry dccp_opts[] = {
45 {.name = "source-port", .id = O_SOURCE_PORT, .type = XTTYPE_PORTRC,
46 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spts)},
47 {.name = "sport", .id = O_SOURCE_PORT, .type = XTTYPE_PORTRC,
48 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spts)},
49 {.name = "destination-port", .id = O_DEST_PORT, .type = XTTYPE_PORTRC,
50 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, dpts)},
51 {.name = "dport", .id = O_DEST_PORT, .type = XTTYPE_PORTRC,
52 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, dpts)},
53 {.name = "dccp-types", .id = O_DCCP_TYPES, .type = XTTYPE_STRING},
54 {.name = "dccp-option", .id = O_DCCP_OPTION, .type = XTTYPE_UINT8,
55 .min = 1, .max = UINT8_MAX, .flags = XTOPT_PUT,
56 XTOPT_POINTER(s, option)},
57 XTOPT_TABLEEND,
Harald Weltee40b11d2005-08-06 21:13:04 +000058};
Jan Engelhardt753bbed2011-04-20 10:17:33 +020059#undef s
Harald Weltee40b11d2005-08-06 21:13:04 +000060
Jan Engelhardt0e2abed2007-10-04 16:25:58 +000061static const char *const dccp_pkt_types[] = {
Harald Weltee40b11d2005-08-06 21:13:04 +000062 [DCCP_PKT_REQUEST] = "REQUEST",
63 [DCCP_PKT_RESPONSE] = "RESPONSE",
64 [DCCP_PKT_DATA] = "DATA",
65 [DCCP_PKT_ACK] = "ACK",
66 [DCCP_PKT_DATAACK] = "DATAACK",
67 [DCCP_PKT_CLOSEREQ] = "CLOSEREQ",
68 [DCCP_PKT_CLOSE] = "CLOSE",
69 [DCCP_PKT_RESET] = "RESET",
70 [DCCP_PKT_SYNC] = "SYNC",
71 [DCCP_PKT_SYNCACK] = "SYNCACK",
72 [DCCP_PKT_INVALID] = "INVALID",
73};
74
Jan Engelhardt7ac40522011-01-07 12:34:04 +010075static uint16_t
Harald Weltee40b11d2005-08-06 21:13:04 +000076parse_dccp_types(const char *typestring)
77{
Jan Engelhardt7ac40522011-01-07 12:34:04 +010078 uint16_t typemask = 0;
Harald Weltee40b11d2005-08-06 21:13:04 +000079 char *ptr, *buffer;
80
81 buffer = strdup(typestring);
82
83 for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
84 unsigned int i;
Jan Engelhardt2c69b552009-04-30 19:32:02 +020085 for (i = 0; i < ARRAY_SIZE(dccp_pkt_types); ++i)
Harald Weltee40b11d2005-08-06 21:13:04 +000086 if (!strcasecmp(dccp_pkt_types[i], ptr)) {
87 typemask |= (1 << i);
88 break;
89 }
Jan Engelhardt2c69b552009-04-30 19:32:02 +020090 if (i == ARRAY_SIZE(dccp_pkt_types))
Jan Engelhardt1829ed42009-02-21 03:29:44 +010091 xtables_error(PARAMETER_PROBLEM,
Harald Weltee40b11d2005-08-06 21:13:04 +000092 "Unknown DCCP type `%s'", ptr);
93 }
94
95 free(buffer);
96 return typemask;
97}
98
Jan Engelhardt753bbed2011-04-20 10:17:33 +020099static void dccp_parse(struct xt_option_call *cb)
Harald Weltee40b11d2005-08-06 21:13:04 +0000100{
Jan Engelhardt753bbed2011-04-20 10:17:33 +0200101 struct xt_dccp_info *einfo = cb->data;
Harald Weltee40b11d2005-08-06 21:13:04 +0000102
Jan Engelhardt753bbed2011-04-20 10:17:33 +0200103 xtables_option_parse(cb);
104 switch (cb->entry->id) {
105 case O_SOURCE_PORT:
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000106 einfo->flags |= XT_DCCP_SRC_PORTS;
Jan Engelhardt753bbed2011-04-20 10:17:33 +0200107 if (cb->invert)
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000108 einfo->invflags |= XT_DCCP_SRC_PORTS;
Harald Weltee40b11d2005-08-06 21:13:04 +0000109 break;
Jan Engelhardt753bbed2011-04-20 10:17:33 +0200110 case O_DEST_PORT:
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000111 einfo->flags |= XT_DCCP_DEST_PORTS;
Jan Engelhardt753bbed2011-04-20 10:17:33 +0200112 if (cb->invert)
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000113 einfo->invflags |= XT_DCCP_DEST_PORTS;
Harald Weltee40b11d2005-08-06 21:13:04 +0000114 break;
Jan Engelhardt753bbed2011-04-20 10:17:33 +0200115 case O_DCCP_TYPES:
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000116 einfo->flags |= XT_DCCP_TYPE;
Jan Engelhardt753bbed2011-04-20 10:17:33 +0200117 einfo->typemask = parse_dccp_types(cb->arg);
118 if (cb->invert)
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000119 einfo->invflags |= XT_DCCP_TYPE;
Harald Weltee40b11d2005-08-06 21:13:04 +0000120 break;
Jan Engelhardt753bbed2011-04-20 10:17:33 +0200121 case O_DCCP_OPTION:
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000122 einfo->flags |= XT_DCCP_OPTION;
Jan Engelhardt753bbed2011-04-20 10:17:33 +0200123 if (cb->invert)
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000124 einfo->invflags |= XT_DCCP_OPTION;
Harald Weltee40b11d2005-08-06 21:13:04 +0000125 break;
Harald Weltee40b11d2005-08-06 21:13:04 +0000126 }
Harald Weltee40b11d2005-08-06 21:13:04 +0000127}
128
Jan Engelhardtdd6e4b92011-05-07 00:05:24 +0200129static const char *
Harald Weltee40b11d2005-08-06 21:13:04 +0000130port_to_service(int port)
131{
Jan Engelhardtdd6e4b92011-05-07 00:05:24 +0200132 const struct servent *service;
Harald Weltee40b11d2005-08-06 21:13:04 +0000133
134 if ((service = getservbyport(htons(port), "dccp")))
135 return service->s_name;
136
137 return NULL;
138}
139
140static void
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100141print_port(uint16_t port, int numeric)
Harald Weltee40b11d2005-08-06 21:13:04 +0000142{
Jan Engelhardtdd6e4b92011-05-07 00:05:24 +0200143 const char *service;
Harald Weltee40b11d2005-08-06 21:13:04 +0000144
145 if (numeric || (service = port_to_service(port)) == NULL)
146 printf("%u", port);
147 else
148 printf("%s", service);
149}
150
151static void
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100152print_ports(const char *name, uint16_t min, uint16_t max,
Harald Weltee40b11d2005-08-06 21:13:04 +0000153 int invert, int numeric)
154{
155 const char *inv = invert ? "!" : "";
156
157 if (min != 0 || max != 0xFFFF || invert) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100158 printf(" %s", name);
Harald Weltee40b11d2005-08-06 21:13:04 +0000159 if (min == max) {
160 printf(":%s", inv);
161 print_port(min, numeric);
162 } else {
163 printf("s:%s", inv);
164 print_port(min, numeric);
165 printf(":");
166 print_port(max, numeric);
167 }
Harald Weltee40b11d2005-08-06 21:13:04 +0000168 }
169}
170
171static void
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100172print_types(uint16_t types, int inverted, int numeric)
Harald Weltee40b11d2005-08-06 21:13:04 +0000173{
174 int have_type = 0;
175
176 if (inverted)
Jan Engelhardt73866352010-12-18 02:04:59 +0100177 printf(" !");
Harald Weltee40b11d2005-08-06 21:13:04 +0000178
Jan Engelhardt73866352010-12-18 02:04:59 +0100179 printf(" ");
Harald Weltee40b11d2005-08-06 21:13:04 +0000180 while (types) {
181 unsigned int i;
182
183 for (i = 0; !(types & (1 << i)); i++);
184
185 if (have_type)
186 printf(",");
187 else
188 have_type = 1;
189
190 if (numeric)
191 printf("%u", i);
192 else
193 printf("%s", dccp_pkt_types[i]);
194
195 types &= ~(1 << i);
196 }
197}
198
199static void
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100200print_option(uint8_t option, int invert, int numeric)
Harald Weltee40b11d2005-08-06 21:13:04 +0000201{
202 if (option || invert)
Jan Engelhardt73866352010-12-18 02:04:59 +0100203 printf(" option=%s%u", invert ? "!" : "", option);
Harald Weltee40b11d2005-08-06 21:13:04 +0000204}
205
Harald Weltee40b11d2005-08-06 21:13:04 +0000206static void
Jan Engelhardt181dead2007-10-04 16:27:07 +0000207dccp_print(const void *ip, const struct xt_entry_match *match, int numeric)
Harald Weltee40b11d2005-08-06 21:13:04 +0000208{
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000209 const struct xt_dccp_info *einfo =
210 (const struct xt_dccp_info *)match->data;
Harald Weltee40b11d2005-08-06 21:13:04 +0000211
Jan Engelhardt73866352010-12-18 02:04:59 +0100212 printf(" dccp");
Harald Weltee40b11d2005-08-06 21:13:04 +0000213
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000214 if (einfo->flags & XT_DCCP_SRC_PORTS) {
Harald Weltee40b11d2005-08-06 21:13:04 +0000215 print_ports("spt", einfo->spts[0], einfo->spts[1],
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000216 einfo->invflags & XT_DCCP_SRC_PORTS,
Harald Weltee40b11d2005-08-06 21:13:04 +0000217 numeric);
218 }
219
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000220 if (einfo->flags & XT_DCCP_DEST_PORTS) {
Harald Weltee40b11d2005-08-06 21:13:04 +0000221 print_ports("dpt", einfo->dpts[0], einfo->dpts[1],
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000222 einfo->invflags & XT_DCCP_DEST_PORTS,
Harald Weltee40b11d2005-08-06 21:13:04 +0000223 numeric);
224 }
225
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000226 if (einfo->flags & XT_DCCP_TYPE) {
Harald Weltee40b11d2005-08-06 21:13:04 +0000227 print_types(einfo->typemask,
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000228 einfo->invflags & XT_DCCP_TYPE,
Harald Weltee40b11d2005-08-06 21:13:04 +0000229 numeric);
230 }
231
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000232 if (einfo->flags & XT_DCCP_OPTION) {
Harald Weltee40b11d2005-08-06 21:13:04 +0000233 print_option(einfo->option,
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000234 einfo->invflags & XT_DCCP_OPTION, numeric);
Harald Weltee40b11d2005-08-06 21:13:04 +0000235 }
236}
237
Jan Engelhardt181dead2007-10-04 16:27:07 +0000238static void dccp_save(const void *ip, const struct xt_entry_match *match)
Harald Weltee40b11d2005-08-06 21:13:04 +0000239{
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000240 const struct xt_dccp_info *einfo =
241 (const struct xt_dccp_info *)match->data;
Harald Weltee40b11d2005-08-06 21:13:04 +0000242
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000243 if (einfo->flags & XT_DCCP_SRC_PORTS) {
244 if (einfo->invflags & XT_DCCP_SRC_PORTS)
Jan Engelhardt73866352010-12-18 02:04:59 +0100245 printf(" !");
Harald Weltee40b11d2005-08-06 21:13:04 +0000246 if (einfo->spts[0] != einfo->spts[1])
Jan Engelhardt73866352010-12-18 02:04:59 +0100247 printf(" --sport %u:%u",
Harald Weltee40b11d2005-08-06 21:13:04 +0000248 einfo->spts[0], einfo->spts[1]);
249 else
Jan Engelhardt73866352010-12-18 02:04:59 +0100250 printf(" --sport %u", einfo->spts[0]);
Harald Weltee40b11d2005-08-06 21:13:04 +0000251 }
252
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000253 if (einfo->flags & XT_DCCP_DEST_PORTS) {
254 if (einfo->invflags & XT_DCCP_DEST_PORTS)
Jan Engelhardt73866352010-12-18 02:04:59 +0100255 printf(" !");
Harald Weltee40b11d2005-08-06 21:13:04 +0000256 if (einfo->dpts[0] != einfo->dpts[1])
Jan Engelhardt73866352010-12-18 02:04:59 +0100257 printf(" --dport %u:%u",
Harald Weltee40b11d2005-08-06 21:13:04 +0000258 einfo->dpts[0], einfo->dpts[1]);
259 else
Jan Engelhardt73866352010-12-18 02:04:59 +0100260 printf(" --dport %u", einfo->dpts[0]);
Harald Weltee40b11d2005-08-06 21:13:04 +0000261 }
262
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000263 if (einfo->flags & XT_DCCP_TYPE) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100264 printf(" --dccp-type");
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000265 print_types(einfo->typemask, einfo->invflags & XT_DCCP_TYPE,0);
Harald Weltee40b11d2005-08-06 21:13:04 +0000266 }
267
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000268 if (einfo->flags & XT_DCCP_OPTION) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100269 printf(" --dccp-option %s%u",
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000270 einfo->typemask & XT_DCCP_OPTION ? "! " : "",
Harald Weltee40b11d2005-08-06 21:13:04 +0000271 einfo->option);
272 }
273}
274
Jan Engelhardt181dead2007-10-04 16:27:07 +0000275static struct xtables_match dccp_match = {
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000276 .name = "dccp",
Jan Engelhardtc5e85732009-06-12 20:55:44 +0200277 .family = NFPROTO_UNSPEC,
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200278 .version = XTABLES_VERSION,
Yasuyuki KOZAKAI3c96c8e2007-07-24 07:19:41 +0000279 .size = XT_ALIGN(sizeof(struct xt_dccp_info)),
280 .userspacesize = XT_ALIGN(sizeof(struct xt_dccp_info)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000281 .help = dccp_help,
Jan Engelhardt181dead2007-10-04 16:27:07 +0000282 .print = dccp_print,
283 .save = dccp_save,
Jan Engelhardt753bbed2011-04-20 10:17:33 +0200284 .x6_parse = dccp_parse,
285 .x6_options = dccp_opts,
Harald Weltee40b11d2005-08-06 21:13:04 +0000286};
287
288void _init(void)
289{
Jan Engelhardt181dead2007-10-04 16:27:07 +0000290 xtables_register_match(&dccp_match);
Harald Weltee40b11d2005-08-06 21:13:04 +0000291}