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_ipv4/ip_tables.h>
18 #include <linux/netfilter_ipv4/ipt_dccp.h>
21 #define DEBUGP(format, first...) printf(format, ##first)
24 #define DEBUGP(format, fist...)
27 /* Initialize the match. */
29 init(struct ipt_entry_match
*m
,
30 unsigned int *nfcache
)
32 struct ipt_dccp_info
*einfo
= (struct ipt_dccp_info
*)m
->data
;
34 memset(einfo
, 0, sizeof(struct ipt_dccp_info
));
37 static void help(void)
40 "DCCP match v%s options\n"
41 " --source-port [!] port[:port] match source port(s)\n"
43 " --destination-port [!] port[:port] match destination port(s)\n"
49 static struct option opts
[] = {
50 { .name
= "source-port", .has_arg
= 1, .flag
= 0, .val
= '1' },
51 { .name
= "sport", .has_arg
= 1, .flag
= 0, .val
= '1' },
52 { .name
= "destination-port", .has_arg
= 1, .flag
= 0, .val
= '2' },
53 { .name
= "dport", .has_arg
= 1, .flag
= 0, .val
= '2' },
54 { .name
= "dccp-types", .has_arg
= 1, .flag
= 0, .val
= '3' },
55 { .name
= "dccp-option", .has_arg
= 1, .flag
= 0, .val
= '4' },
60 parse_dccp_ports(const char *portstring
,
66 buffer
= strdup(portstring
);
67 DEBUGP("%s\n", portstring
);
68 if ((cp
= strchr(buffer
, ':')) == NULL
) {
69 ports
[0] = ports
[1] = parse_port(buffer
, "dccp");
75 ports
[0] = buffer
[0] ? parse_port(buffer
, "dccp") : 0;
76 ports
[1] = cp
[0] ? parse_port(cp
, "dccp") : 0xFFFF;
78 if (ports
[0] > ports
[1])
79 exit_error(PARAMETER_PROBLEM
,
80 "invalid portrange (min > max)");
85 static char *dccp_pkt_types
[] = {
86 [DCCP_PKT_REQUEST
] = "REQUEST",
87 [DCCP_PKT_RESPONSE
] = "RESPONSE",
88 [DCCP_PKT_DATA
] = "DATA",
89 [DCCP_PKT_ACK
] = "ACK",
90 [DCCP_PKT_DATAACK
] = "DATAACK",
91 [DCCP_PKT_CLOSEREQ
] = "CLOSEREQ",
92 [DCCP_PKT_CLOSE
] = "CLOSE",
93 [DCCP_PKT_RESET
] = "RESET",
94 [DCCP_PKT_SYNC
] = "SYNC",
95 [DCCP_PKT_SYNCACK
] = "SYNCACK",
96 [DCCP_PKT_INVALID
] = "INVALID",
100 parse_dccp_types(const char *typestring
)
102 u_int16_t typemask
= 0;
105 buffer
= strdup(typestring
);
107 for (ptr
= strtok(buffer
, ","); ptr
; ptr
= strtok(NULL
, ",")) {
109 for (i
= 0; i
< sizeof(dccp_pkt_types
)/sizeof(char *); i
++) {
110 if (!strcasecmp(dccp_pkt_types
[i
], ptr
)) {
111 typemask
|= (1 << i
);
115 if (i
== sizeof(dccp_pkt_types
)/sizeof(char *))
116 exit_error(PARAMETER_PROBLEM
,
117 "Unknown DCCP type `%s'", ptr
);
124 static u_int8_t
parse_dccp_option(char *optstring
)
128 if (string_to_number(optstring
, 1, 255, &ret
) == -1)
129 exit_error(PARAMETER_PROBLEM
, "Bad DCCP option `%s'",
132 return (u_int8_t
)ret
;
136 parse(int c
, char **argv
, int invert
, unsigned int *flags
,
137 const struct ipt_entry
*entry
,
138 unsigned int *nfcache
,
139 struct ipt_entry_match
**match
)
141 struct ipt_dccp_info
*einfo
142 = (struct ipt_dccp_info
*)(*match
)->data
;
146 if (*flags
& IPT_DCCP_SRC_PORTS
)
147 exit_error(PARAMETER_PROBLEM
,
148 "Only one `--source-port' allowed");
149 einfo
->flags
|= IPT_DCCP_SRC_PORTS
;
150 check_inverse(optarg
, &invert
, &optind
, 0);
151 parse_dccp_ports(argv
[optind
-1], einfo
->spts
);
153 einfo
->invflags
|= IPT_DCCP_SRC_PORTS
;
154 *flags
|= IPT_DCCP_SRC_PORTS
;
158 if (*flags
& IPT_DCCP_DEST_PORTS
)
159 exit_error(PARAMETER_PROBLEM
,
160 "Only one `--destination-port' allowed");
161 einfo
->flags
|= IPT_DCCP_DEST_PORTS
;
162 check_inverse(optarg
, &invert
, &optind
, 0);
163 parse_dccp_ports(argv
[optind
-1], einfo
->dpts
);
165 einfo
->invflags
|= IPT_DCCP_DEST_PORTS
;
166 *flags
|= IPT_DCCP_DEST_PORTS
;
170 if (*flags
& IPT_DCCP_TYPE
)
171 exit_error(PARAMETER_PROBLEM
,
172 "Only one `--dccp-types' allowed");
173 einfo
->flags
|= IPT_DCCP_TYPE
;
174 check_inverse(optarg
, &invert
, &optind
, 0);
175 einfo
->typemask
= parse_dccp_types(argv
[optind
-1]);
177 einfo
->invflags
|= IPT_DCCP_TYPE
;
178 *flags
|= IPT_DCCP_TYPE
;
182 if (*flags
& IPT_DCCP_OPTION
)
183 exit_error(PARAMETER_PROBLEM
,
184 "Only one `--dccp-option' allowed");
185 einfo
->flags
|= IPT_DCCP_OPTION
;
186 check_inverse(optarg
, &invert
, &optind
, 0);
187 einfo
->option
= parse_dccp_option(argv
[optind
-1]);
189 einfo
->invflags
|= IPT_DCCP_OPTION
;
190 *flags
|= IPT_DCCP_OPTION
;
199 final_check(unsigned int flags
)
204 port_to_service(int port
)
206 struct servent
*service
;
208 if ((service
= getservbyport(htons(port
), "dccp")))
209 return service
->s_name
;
215 print_port(u_int16_t port
, int numeric
)
219 if (numeric
|| (service
= port_to_service(port
)) == NULL
)
222 printf("%s", service
);
226 print_ports(const char *name
, u_int16_t min
, u_int16_t max
,
227 int invert
, int numeric
)
229 const char *inv
= invert
? "!" : "";
231 if (min
!= 0 || max
!= 0xFFFF || invert
) {
235 print_port(min
, numeric
);
238 print_port(min
, numeric
);
240 print_port(max
, numeric
);
247 print_types(u_int16_t types
, int inverted
, int numeric
)
257 for (i
= 0; !(types
& (1 << i
)); i
++);
267 printf("%s", dccp_pkt_types
[i
]);
274 print_option(u_int8_t option
, int invert
, int numeric
)
276 if (option
|| invert
)
277 printf("option=%s%u ", invert
? "!" : "", option
);
280 /* Prints out the matchinfo. */
282 print(const struct ipt_ip
*ip
,
283 const struct ipt_entry_match
*match
,
286 const struct ipt_dccp_info
*einfo
=
287 (const struct ipt_dccp_info
*)match
->data
;
291 if (einfo
->flags
& IPT_DCCP_SRC_PORTS
) {
292 print_ports("spt", einfo
->spts
[0], einfo
->spts
[1],
293 einfo
->invflags
& IPT_DCCP_SRC_PORTS
,
297 if (einfo
->flags
& IPT_DCCP_DEST_PORTS
) {
298 print_ports("dpt", einfo
->dpts
[0], einfo
->dpts
[1],
299 einfo
->invflags
& IPT_DCCP_DEST_PORTS
,
303 if (einfo
->flags
& IPT_DCCP_TYPE
) {
304 print_types(einfo
->typemask
,
305 einfo
->invflags
& IPT_DCCP_TYPE
,
309 if (einfo
->flags
& IPT_DCCP_OPTION
) {
310 print_option(einfo
->option
,
311 einfo
->invflags
& IPT_DCCP_OPTION
, numeric
);
315 /* Saves the union ipt_matchinfo in parsable form to stdout. */
317 save(const struct ipt_ip
*ip
,
318 const struct ipt_entry_match
*match
)
320 const struct ipt_dccp_info
*einfo
=
321 (const struct ipt_dccp_info
*)match
->data
;
323 if (einfo
->flags
& IPT_DCCP_SRC_PORTS
) {
324 if (einfo
->invflags
& IPT_DCCP_SRC_PORTS
)
326 if (einfo
->spts
[0] != einfo
->spts
[1])
327 printf("--sport %u:%u ",
328 einfo
->spts
[0], einfo
->spts
[1]);
330 printf("--sport %u ", einfo
->spts
[0]);
333 if (einfo
->flags
& IPT_DCCP_DEST_PORTS
) {
334 if (einfo
->invflags
& IPT_DCCP_DEST_PORTS
)
336 if (einfo
->dpts
[0] != einfo
->dpts
[1])
337 printf("--dport %u:%u ",
338 einfo
->dpts
[0], einfo
->dpts
[1]);
340 printf("--dport %u ", einfo
->dpts
[0]);
343 if (einfo
->flags
& IPT_DCCP_TYPE
) {
344 printf("--dccp-type ");
345 print_types(einfo
->typemask
, einfo
->invflags
& IPT_DCCP_TYPE
,0);
348 if (einfo
->flags
& IPT_DCCP_OPTION
) {
349 printf("--dccp-option %s%u ",
350 einfo
->typemask
& IPT_DCCP_OPTION
? "! " : "",
356 struct iptables_match dccp
358 .version
= IPTABLES_VERSION
,
359 .size
= IPT_ALIGN(sizeof(struct ipt_dccp_info
)),
360 .userspacesize
= IPT_ALIGN(sizeof(struct ipt_dccp_info
)),
364 .final_check
= &final_check
,
372 register_match(&dccp
);