1 /* Shared library add-on to iptables for DCCP matching
3 * (C) 2005 by Harald Welte <laforge@netfilter.org>
5 * This program is distributed under the terms of GNU GPL v2, 1991
16 #include <linux/dccp.h>
17 #include <linux/netfilter/x_tables.h>
18 #include <linux/netfilter/xt_dccp.h>
21 #define DEBUGP(format, first...) printf(format, ##first)
24 #define DEBUGP(format, fist...)
27 /* Initialize the match. */
28 static void dccp_init(struct xt_entry_match *m)
30 struct xt_dccp_info *einfo = (struct xt_dccp_info *)m->data;
32 memset(einfo, 0, sizeof(struct xt_dccp_info));
35 static void dccp_help(void)
38 "dccp match options\n"
39 " --source-port [!] port[:port] match source port(s)\n"
41 " --destination-port [!] port[:port] match destination port(s)\n"
45 static const struct option dccp_opts[] = {
46 { .name = "source-port", .has_arg = 1, .val = '1' },
47 { .name = "sport", .has_arg = 1, .val = '1' },
48 { .name = "destination-port", .has_arg = 1, .val = '2' },
49 { .name = "dport", .has_arg = 1, .val = '2' },
50 { .name = "dccp-types", .has_arg = 1, .val = '3' },
51 { .name = "dccp-option", .has_arg = 1, .val = '4' },
56 parse_dccp_ports(const char *portstring,
62 buffer = strdup(portstring);
63 DEBUGP("%s\n", portstring);
64 if ((cp = strchr(buffer, ':')) == NULL) {
65 ports[0] = ports[1] = parse_port(buffer, "dccp");
71 ports[0] = buffer[0] ? parse_port(buffer, "dccp") : 0;
72 ports[1] = cp[0] ? parse_port(cp, "dccp") : 0xFFFF;
74 if (ports[0] > ports[1])
75 exit_error(PARAMETER_PROBLEM,
76 "invalid portrange (min > max)");
81 static const char *const dccp_pkt_types[] = {
82 [DCCP_PKT_REQUEST] = "REQUEST",
83 [DCCP_PKT_RESPONSE] = "RESPONSE",
84 [DCCP_PKT_DATA] = "DATA",
85 [DCCP_PKT_ACK] = "ACK",
86 [DCCP_PKT_DATAACK] = "DATAACK",
87 [DCCP_PKT_CLOSEREQ] = "CLOSEREQ",
88 [DCCP_PKT_CLOSE] = "CLOSE",
89 [DCCP_PKT_RESET] = "RESET",
90 [DCCP_PKT_SYNC] = "SYNC",
91 [DCCP_PKT_SYNCACK] = "SYNCACK",
92 [DCCP_PKT_INVALID] = "INVALID",
96 parse_dccp_types(const char *typestring)
98 u_int16_t typemask = 0;
101 buffer = strdup(typestring);
103 for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
105 for (i = 0; i < sizeof(dccp_pkt_types)/sizeof(char *); i++) {
106 if (!strcasecmp(dccp_pkt_types[i], ptr)) {
107 typemask |= (1 << i);
111 if (i == sizeof(dccp_pkt_types)/sizeof(char *))
112 exit_error(PARAMETER_PROBLEM,
113 "Unknown DCCP type `%s'", ptr);
120 static u_int8_t parse_dccp_option(char *optstring)
124 if (string_to_number(optstring, 1, 255, &ret) == -1)
125 exit_error(PARAMETER_PROBLEM, "Bad DCCP option `%s'",
128 return (u_int8_t)ret;
132 dccp_parse(int c, char **argv, int invert, unsigned int *flags,
133 const void *entry, struct xt_entry_match **match)
135 struct xt_dccp_info *einfo
136 = (struct xt_dccp_info *)(*match)->data;
140 if (*flags & XT_DCCP_SRC_PORTS)
141 exit_error(PARAMETER_PROBLEM,
142 "Only one `--source-port' allowed");
143 einfo->flags |= XT_DCCP_SRC_PORTS;
144 check_inverse(optarg, &invert, &optind, 0);
145 parse_dccp_ports(argv[optind-1], einfo->spts);
147 einfo->invflags |= XT_DCCP_SRC_PORTS;
148 *flags |= XT_DCCP_SRC_PORTS;
152 if (*flags & XT_DCCP_DEST_PORTS)
153 exit_error(PARAMETER_PROBLEM,
154 "Only one `--destination-port' allowed");
155 einfo->flags |= XT_DCCP_DEST_PORTS;
156 check_inverse(optarg, &invert, &optind, 0);
157 parse_dccp_ports(argv[optind-1], einfo->dpts);
159 einfo->invflags |= XT_DCCP_DEST_PORTS;
160 *flags |= XT_DCCP_DEST_PORTS;
164 if (*flags & XT_DCCP_TYPE)
165 exit_error(PARAMETER_PROBLEM,
166 "Only one `--dccp-types' allowed");
167 einfo->flags |= XT_DCCP_TYPE;
168 check_inverse(optarg, &invert, &optind, 0);
169 einfo->typemask = parse_dccp_types(argv[optind-1]);
171 einfo->invflags |= XT_DCCP_TYPE;
172 *flags |= XT_DCCP_TYPE;
176 if (*flags & XT_DCCP_OPTION)
177 exit_error(PARAMETER_PROBLEM,
178 "Only one `--dccp-option' allowed");
179 einfo->flags |= XT_DCCP_OPTION;
180 check_inverse(optarg, &invert, &optind, 0);
181 einfo->option = parse_dccp_option(argv[optind-1]);
183 einfo->invflags |= XT_DCCP_OPTION;
184 *flags |= XT_DCCP_OPTION;
193 port_to_service(int port)
195 struct servent *service;
197 if ((service = getservbyport(htons(port), "dccp")))
198 return service->s_name;
204 print_port(u_int16_t port, int numeric)
208 if (numeric || (service = port_to_service(port)) == NULL)
211 printf("%s", service);
215 print_ports(const char *name, u_int16_t min, u_int16_t max,
216 int invert, int numeric)
218 const char *inv = invert ? "!" : "";
220 if (min != 0 || max != 0xFFFF || invert) {
224 print_port(min, numeric);
227 print_port(min, numeric);
229 print_port(max, numeric);
236 print_types(u_int16_t types, int inverted, int numeric)
246 for (i = 0; !(types & (1 << i)); i++);
256 printf("%s", dccp_pkt_types[i]);
263 print_option(u_int8_t option, int invert, int numeric)
265 if (option || invert)
266 printf("option=%s%u ", invert ? "!" : "", option);
269 /* Prints out the matchinfo. */
271 dccp_print(const void *ip, const struct xt_entry_match *match, int numeric)
273 const struct xt_dccp_info *einfo =
274 (const struct xt_dccp_info *)match->data;
278 if (einfo->flags & XT_DCCP_SRC_PORTS) {
279 print_ports("spt", einfo->spts[0], einfo->spts[1],
280 einfo->invflags & XT_DCCP_SRC_PORTS,
284 if (einfo->flags & XT_DCCP_DEST_PORTS) {
285 print_ports("dpt", einfo->dpts[0], einfo->dpts[1],
286 einfo->invflags & XT_DCCP_DEST_PORTS,
290 if (einfo->flags & XT_DCCP_TYPE) {
291 print_types(einfo->typemask,
292 einfo->invflags & XT_DCCP_TYPE,
296 if (einfo->flags & XT_DCCP_OPTION) {
297 print_option(einfo->option,
298 einfo->invflags & XT_DCCP_OPTION, numeric);
302 /* Saves the union ipt_matchinfo in parsable form to stdout. */
303 static void dccp_save(const void *ip, const struct xt_entry_match *match)
305 const struct xt_dccp_info *einfo =
306 (const struct xt_dccp_info *)match->data;
308 if (einfo->flags & XT_DCCP_SRC_PORTS) {
309 if (einfo->invflags & XT_DCCP_SRC_PORTS)
311 if (einfo->spts[0] != einfo->spts[1])
312 printf("--sport %u:%u ",
313 einfo->spts[0], einfo->spts[1]);
315 printf("--sport %u ", einfo->spts[0]);
318 if (einfo->flags & XT_DCCP_DEST_PORTS) {
319 if (einfo->invflags & XT_DCCP_DEST_PORTS)
321 if (einfo->dpts[0] != einfo->dpts[1])
322 printf("--dport %u:%u ",
323 einfo->dpts[0], einfo->dpts[1]);
325 printf("--dport %u ", einfo->dpts[0]);
328 if (einfo->flags & XT_DCCP_TYPE) {
329 printf("--dccp-type ");
330 print_types(einfo->typemask, einfo->invflags & XT_DCCP_TYPE,0);
333 if (einfo->flags & XT_DCCP_OPTION) {
334 printf("--dccp-option %s%u ",
335 einfo->typemask & XT_DCCP_OPTION ? "! " : "",
340 static struct xtables_match dccp_match = {
343 .version = XTABLES_VERSION,
344 .size = XT_ALIGN(sizeof(struct xt_dccp_info)),
345 .userspacesize = XT_ALIGN(sizeof(struct xt_dccp_info)),
351 .extra_opts = dccp_opts,
354 static struct xtables_match dccp_match6 = {
357 .version = XTABLES_VERSION,
358 .size = XT_ALIGN(sizeof(struct xt_dccp_info)),
359 .userspacesize = XT_ALIGN(sizeof(struct xt_dccp_info)),
365 .extra_opts = dccp_opts,
370 xtables_register_match(&dccp_match);
371 xtables_register_match(&dccp_match6);