]> granicus.if.org Git - ipset/blob - lib/ipset_hash_ipport.c
21669220f377536d857e147a928024d4d82f75dd
[ipset] / lib / ipset_hash_ipport.c
1 /* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation.
6  */
7 #include <libipset/data.h>                      /* IPSET_OPT_* */
8 #include <libipset/parse.h>                     /* parser functions */
9 #include <libipset/print.h>                     /* printing functions */
10 #include <libipset/ui.h>                        /* ipset_port_usage */
11 #include <libipset/types.h>                     /* prototypes */
12
13 /* Parse commandline arguments */
14 static const struct ipset_arg hash_ipport_create_args1[] = {
15         { .name = { "family", NULL },
16           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_FAMILY,
17           .parse = ipset_parse_family,          .print = ipset_print_family,
18         },
19         /* Alias: family inet */
20         { .name = { "-4", NULL },
21           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_FAMILY,
22           .parse = ipset_parse_family,
23         },
24         /* Alias: family inet6 */
25         { .name = { "-6", NULL },
26           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_FAMILY,
27           .parse = ipset_parse_family,
28         },
29         { .name = { "hashsize", NULL },
30           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_HASHSIZE,
31           .parse = ipset_parse_uint32,          .print = ipset_print_number,
32         },
33         { .name = { "maxelem", NULL },
34           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_MAXELEM,
35           .parse = ipset_parse_uint32,          .print = ipset_print_number,
36         },
37         { .name = { "timeout", NULL },
38           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
39           .parse = ipset_parse_timeout,         .print = ipset_print_number,
40         },
41         /* Backward compatibility */
42         { .name = { "probes", NULL },
43           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROBES,
44           .parse = ipset_parse_ignored,         .print = ipset_print_number,
45         },
46         { .name = { "resize", NULL },
47           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_RESIZE,
48           .parse = ipset_parse_ignored,         .print = ipset_print_number,
49         },
50         { .name = { "from", NULL },
51           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
52           .parse = ipset_parse_ignored,
53         },
54         { .name = { "to", NULL },
55           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP_TO,
56           .parse = ipset_parse_ignored,
57         },
58         { .name = { "network", NULL },
59           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
60           .parse = ipset_parse_ignored,
61         },
62         { },
63 };
64
65 static const struct ipset_arg hash_ipport_add_args1[] = {
66         { .name = { "timeout", NULL },
67           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
68           .parse = ipset_parse_timeout,         .print = ipset_print_number,
69         },
70         { },
71 };
72
73 static const char hash_ipport_usage1[] =
74 "create SETNAME hash:ip,port\n"
75 "               [family inet|inet6]\n"
76 "               [hashsize VALUE] [maxelem VALUE]\n"
77 "               [timeout VALUE]\n"
78 "add    SETNAME IP,PROTO:PORT [timeout VALUE]\n"
79 "del    SETNAME IP,PROTO:PORT\n"
80 "test   SETNAME IP,PROTO:PORT\n\n"
81 "where depending on the INET family\n"
82 "      IP is a valid IPv4 or IPv6 address (or hostname).\n"
83 "      Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
84 "      is supported for IPv4.\n"
85 "      Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
86 "      port range is supported both for IPv4 and IPv6.\n";
87
88 static struct ipset_type ipset_hash_ipport1 = {
89         .name = "hash:ip,port",
90         .alias = { "ipporthash", NULL },
91         .revision = 1,
92         .family = NFPROTO_IPSET_IPV46,
93         .dimension = IPSET_DIM_TWO,
94         .elem = {
95                 [IPSET_DIM_ONE - 1] = {
96                         .parse = ipset_parse_ip4_single6,
97                         .print = ipset_print_ip,
98                         .opt = IPSET_OPT_IP
99                 },
100                 [IPSET_DIM_TWO - 1] = {
101                         .parse = ipset_parse_proto_port,
102                         .print = ipset_print_proto_port,
103                         .opt = IPSET_OPT_PORT
104                 },
105         },
106         .args = {
107                 [IPSET_CREATE] = hash_ipport_create_args1,
108                 [IPSET_ADD] = hash_ipport_add_args1,
109         },
110         .mandatory = {
111                 [IPSET_CREATE] = 0,
112                 [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
113                         | IPSET_FLAG(IPSET_OPT_PROTO)
114                         | IPSET_FLAG(IPSET_OPT_PORT),
115                 [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
116                         | IPSET_FLAG(IPSET_OPT_PROTO)
117                         | IPSET_FLAG(IPSET_OPT_PORT),
118                 [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
119                         | IPSET_FLAG(IPSET_OPT_PROTO)
120                         | IPSET_FLAG(IPSET_OPT_PORT),
121         },
122         .full = {
123                 [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
124                         | IPSET_FLAG(IPSET_OPT_MAXELEM)
125                         | IPSET_FLAG(IPSET_OPT_TIMEOUT),
126                 [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
127                         | IPSET_FLAG(IPSET_OPT_IP_TO)
128                         | IPSET_FLAG(IPSET_OPT_PORT)
129                         | IPSET_FLAG(IPSET_OPT_PORT_TO)
130                         | IPSET_FLAG(IPSET_OPT_PROTO)
131                         | IPSET_FLAG(IPSET_OPT_TIMEOUT),
132                 [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
133                         | IPSET_FLAG(IPSET_OPT_IP_TO)
134                         | IPSET_FLAG(IPSET_OPT_PORT)
135                         | IPSET_FLAG(IPSET_OPT_PORT_TO)
136                         | IPSET_FLAG(IPSET_OPT_PROTO),
137                 [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
138                         | IPSET_FLAG(IPSET_OPT_PORT)
139                         | IPSET_FLAG(IPSET_OPT_PROTO),
140         },
141
142         .usage = hash_ipport_usage1,
143         .usagefn = ipset_port_usage,
144         .description = "SCTP and UDPLITE support",
145 };
146
147 /* Parse commandline arguments */
148 static const struct ipset_arg hash_ipport_create_args2[] = {
149         { .name = { "family", NULL },
150           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_FAMILY,
151           .parse = ipset_parse_family,          .print = ipset_print_family,
152         },
153         /* Alias: family inet */
154         { .name = { "-4", NULL },
155           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_FAMILY,
156           .parse = ipset_parse_family,
157         },
158         /* Alias: family inet6 */
159         { .name = { "-6", NULL },
160           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_FAMILY,
161           .parse = ipset_parse_family,
162         },
163         { .name = { "hashsize", NULL },
164           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_HASHSIZE,
165           .parse = ipset_parse_uint32,          .print = ipset_print_number,
166         },
167         { .name = { "maxelem", NULL },
168           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_MAXELEM,
169           .parse = ipset_parse_uint32,          .print = ipset_print_number,
170         },
171         { .name = { "timeout", NULL },
172           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
173           .parse = ipset_parse_timeout,         .print = ipset_print_number,
174         },
175         { .name = { "counters", NULL },
176           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_COUNTERS,
177           .parse = ipset_parse_flag,            .print = ipset_print_flag,
178         },
179         /* Backward compatibility */
180         { .name = { "probes", NULL },
181           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROBES,
182           .parse = ipset_parse_ignored,         .print = ipset_print_number,
183         },
184         { .name = { "resize", NULL },
185           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_RESIZE,
186           .parse = ipset_parse_ignored,         .print = ipset_print_number,
187         },
188         { .name = { "from", NULL },
189           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
190           .parse = ipset_parse_ignored,
191         },
192         { .name = { "to", NULL },
193           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP_TO,
194           .parse = ipset_parse_ignored,
195         },
196         { .name = { "network", NULL },
197           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
198           .parse = ipset_parse_ignored,
199         },
200         { },
201 };
202
203 static const struct ipset_arg hash_ipport_add_args2[] = {
204         { .name = { "timeout", NULL },
205           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
206           .parse = ipset_parse_timeout,         .print = ipset_print_number,
207         },
208         { .name = { "packets", NULL },
209           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PACKETS,
210           .parse = ipset_parse_uint64,          .print = ipset_print_number,
211         },
212         { .name = { "bytes", NULL },
213           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_BYTES,
214           .parse = ipset_parse_uint64,          .print = ipset_print_number,
215         },
216         { },
217 };
218
219 static const char hash_ipport_usage2[] =
220 "create SETNAME hash:ip,port\n"
221 "               [family inet|inet6]\n"
222 "               [hashsize VALUE] [maxelem VALUE]\n"
223 "               [timeout VALUE] [counters]\n"
224 "add    SETNAME IP,PROTO:PORT [timeout VALUE]\n"
225 "               [packets VALUE] [bytes VALUE]\n"
226 "del    SETNAME IP,PROTO:PORT\n"
227 "test   SETNAME IP,PROTO:PORT\n\n"
228 "where depending on the INET family\n"
229 "      IP is a valid IPv4 or IPv6 address (or hostname).\n"
230 "      Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
231 "      is supported for IPv4.\n"
232 "      Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
233 "      port range is supported both for IPv4 and IPv6.\n";
234
235 static struct ipset_type ipset_hash_ipport2 = {
236         .name = "hash:ip,port",
237         .alias = { "ipporthash", NULL },
238         .revision = 2,
239         .family = NFPROTO_IPSET_IPV46,
240         .dimension = IPSET_DIM_TWO,
241         .elem = {
242                 [IPSET_DIM_ONE - 1] = {
243                         .parse = ipset_parse_ip4_single6,
244                         .print = ipset_print_ip,
245                         .opt = IPSET_OPT_IP
246                 },
247                 [IPSET_DIM_TWO - 1] = {
248                         .parse = ipset_parse_proto_port,
249                         .print = ipset_print_proto_port,
250                         .opt = IPSET_OPT_PORT
251                 },
252         },
253         .args = {
254                 [IPSET_CREATE] = hash_ipport_create_args2,
255                 [IPSET_ADD] = hash_ipport_add_args2,
256         },
257         .mandatory = {
258                 [IPSET_CREATE] = 0,
259                 [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
260                         | IPSET_FLAG(IPSET_OPT_PROTO)
261                         | IPSET_FLAG(IPSET_OPT_PORT),
262                 [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
263                         | IPSET_FLAG(IPSET_OPT_PROTO)
264                         | IPSET_FLAG(IPSET_OPT_PORT),
265                 [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
266                         | IPSET_FLAG(IPSET_OPT_PROTO)
267                         | IPSET_FLAG(IPSET_OPT_PORT),
268         },
269         .full = {
270                 [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
271                         | IPSET_FLAG(IPSET_OPT_MAXELEM)
272                         | IPSET_FLAG(IPSET_OPT_TIMEOUT)
273                         | IPSET_FLAG(IPSET_OPT_COUNTERS),
274                 [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
275                         | IPSET_FLAG(IPSET_OPT_IP_TO)
276                         | IPSET_FLAG(IPSET_OPT_PORT)
277                         | IPSET_FLAG(IPSET_OPT_PORT_TO)
278                         | IPSET_FLAG(IPSET_OPT_PROTO)
279                         | IPSET_FLAG(IPSET_OPT_TIMEOUT)
280                         | IPSET_FLAG(IPSET_OPT_PACKETS)
281                         | IPSET_FLAG(IPSET_OPT_BYTES),
282                 [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
283                         | IPSET_FLAG(IPSET_OPT_IP_TO)
284                         | IPSET_FLAG(IPSET_OPT_PORT)
285                         | IPSET_FLAG(IPSET_OPT_PORT_TO)
286                         | IPSET_FLAG(IPSET_OPT_PROTO),
287                 [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
288                         | IPSET_FLAG(IPSET_OPT_PORT)
289                         | IPSET_FLAG(IPSET_OPT_PROTO),
290         },
291
292         .usage = hash_ipport_usage2,
293         .usagefn = ipset_port_usage,
294         .description = "counters support",
295 };
296
297 /* Parse commandline arguments */
298 static const struct ipset_arg hash_ipport_create_args3[] = {
299         { .name = { "family", NULL },
300           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_FAMILY,
301           .parse = ipset_parse_family,          .print = ipset_print_family,
302         },
303         /* Alias: family inet */
304         { .name = { "-4", NULL },
305           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_FAMILY,
306           .parse = ipset_parse_family,
307         },
308         /* Alias: family inet6 */
309         { .name = { "-6", NULL },
310           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_FAMILY,
311           .parse = ipset_parse_family,
312         },
313         { .name = { "hashsize", NULL },
314           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_HASHSIZE,
315           .parse = ipset_parse_uint32,          .print = ipset_print_number,
316         },
317         { .name = { "maxelem", NULL },
318           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_MAXELEM,
319           .parse = ipset_parse_uint32,          .print = ipset_print_number,
320         },
321         { .name = { "timeout", NULL },
322           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
323           .parse = ipset_parse_timeout,         .print = ipset_print_number,
324         },
325         { .name = { "counters", NULL },
326           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_COUNTERS,
327           .parse = ipset_parse_flag,            .print = ipset_print_flag,
328         },
329         { .name = { "comment", NULL },
330           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_CREATE_COMMENT,
331           .parse = ipset_parse_flag,            .print = ipset_print_flag,
332         },
333         /* Backward compatibility */
334         { .name = { "probes", NULL },
335           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROBES,
336           .parse = ipset_parse_ignored,         .print = ipset_print_number,
337         },
338         { .name = { "resize", NULL },
339           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_RESIZE,
340           .parse = ipset_parse_ignored,         .print = ipset_print_number,
341         },
342         { .name = { "from", NULL },
343           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
344           .parse = ipset_parse_ignored,
345         },
346         { .name = { "to", NULL },
347           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP_TO,
348           .parse = ipset_parse_ignored,
349         },
350         { .name = { "network", NULL },
351           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
352           .parse = ipset_parse_ignored,
353         },
354         { },
355 };
356
357 static const struct ipset_arg hash_ipport_add_args3[] = {
358         { .name = { "timeout", NULL },
359           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
360           .parse = ipset_parse_timeout,         .print = ipset_print_number,
361         },
362         { .name = { "packets", NULL },
363           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PACKETS,
364           .parse = ipset_parse_uint64,          .print = ipset_print_number,
365         },
366         { .name = { "bytes", NULL },
367           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_BYTES,
368           .parse = ipset_parse_uint64,          .print = ipset_print_number,
369         },
370         { .name = { "comment", NULL },
371           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_ADT_COMMENT,
372           .parse = ipset_parse_comment,         .print = ipset_print_comment,
373         },
374         { },
375 };
376
377 static const char hash_ipport_usage3[] =
378 "create SETNAME hash:ip,port\n"
379 "               [family inet|inet6]\n"
380 "               [hashsize VALUE] [maxelem VALUE]\n"
381 "               [timeout VALUE] [counters] [comment]\n"
382 "add    SETNAME IP,PROTO:PORT [timeout VALUE]\n"
383 "               [packets VALUE] [bytes VALUE] [comment \"string\"]\n"
384 "del    SETNAME IP,PROTO:PORT\n"
385 "test   SETNAME IP,PROTO:PORT\n\n"
386 "where depending on the INET family\n"
387 "      IP is a valid IPv4 or IPv6 address (or hostname).\n"
388 "      Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
389 "      is supported for IPv4.\n"
390 "      Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
391 "      port range is supported both for IPv4 and IPv6.\n";
392
393 static struct ipset_type ipset_hash_ipport3 = {
394         .name = "hash:ip,port",
395         .alias = { "ipporthash", NULL },
396         .revision = 3,
397         .family = NFPROTO_IPSET_IPV46,
398         .dimension = IPSET_DIM_TWO,
399         .elem = {
400                 [IPSET_DIM_ONE - 1] = {
401                         .parse = ipset_parse_ip4_single6,
402                         .print = ipset_print_ip,
403                         .opt = IPSET_OPT_IP
404                 },
405                 [IPSET_DIM_TWO - 1] = {
406                         .parse = ipset_parse_proto_port,
407                         .print = ipset_print_proto_port,
408                         .opt = IPSET_OPT_PORT
409                 },
410         },
411         .args = {
412                 [IPSET_CREATE] = hash_ipport_create_args3,
413                 [IPSET_ADD] = hash_ipport_add_args3,
414         },
415         .mandatory = {
416                 [IPSET_CREATE] = 0,
417                 [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
418                         | IPSET_FLAG(IPSET_OPT_PROTO)
419                         | IPSET_FLAG(IPSET_OPT_PORT),
420                 [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
421                         | IPSET_FLAG(IPSET_OPT_PROTO)
422                         | IPSET_FLAG(IPSET_OPT_PORT),
423                 [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
424                         | IPSET_FLAG(IPSET_OPT_PROTO)
425                         | IPSET_FLAG(IPSET_OPT_PORT),
426         },
427         .full = {
428                 [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
429                         | IPSET_FLAG(IPSET_OPT_MAXELEM)
430                         | IPSET_FLAG(IPSET_OPT_TIMEOUT)
431                         | IPSET_FLAG(IPSET_OPT_COUNTERS)
432                         | IPSET_FLAG(IPSET_OPT_CREATE_COMMENT),
433                 [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
434                         | IPSET_FLAG(IPSET_OPT_IP_TO)
435                         | IPSET_FLAG(IPSET_OPT_PORT)
436                         | IPSET_FLAG(IPSET_OPT_PORT_TO)
437                         | IPSET_FLAG(IPSET_OPT_PROTO)
438                         | IPSET_FLAG(IPSET_OPT_TIMEOUT)
439                         | IPSET_FLAG(IPSET_OPT_PACKETS)
440                         | IPSET_FLAG(IPSET_OPT_BYTES)
441                         | IPSET_FLAG(IPSET_OPT_ADT_COMMENT),
442                 [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
443                         | IPSET_FLAG(IPSET_OPT_IP_TO)
444                         | IPSET_FLAG(IPSET_OPT_PORT)
445                         | IPSET_FLAG(IPSET_OPT_PORT_TO)
446                         | IPSET_FLAG(IPSET_OPT_PROTO),
447                 [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
448                         | IPSET_FLAG(IPSET_OPT_PORT)
449                         | IPSET_FLAG(IPSET_OPT_PROTO),
450         },
451
452         .usage = hash_ipport_usage3,
453         .usagefn = ipset_port_usage,
454         .description = "comment support",
455 };
456
457 /* Parse commandline arguments */
458 static const struct ipset_arg hash_ipport_create_args4[] = {
459         { .name = { "family", NULL },
460           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_FAMILY,
461           .parse = ipset_parse_family,          .print = ipset_print_family,
462         },
463         /* Alias: family inet */
464         { .name = { "-4", NULL },
465           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_FAMILY,
466           .parse = ipset_parse_family,
467         },
468         /* Alias: family inet6 */
469         { .name = { "-6", NULL },
470           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_FAMILY,
471           .parse = ipset_parse_family,
472         },
473         { .name = { "hashsize", NULL },
474           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_HASHSIZE,
475           .parse = ipset_parse_uint32,          .print = ipset_print_number,
476         },
477         { .name = { "maxelem", NULL },
478           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_MAXELEM,
479           .parse = ipset_parse_uint32,          .print = ipset_print_number,
480         },
481         { .name = { "timeout", NULL },
482           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
483           .parse = ipset_parse_timeout,         .print = ipset_print_number,
484         },
485         { .name = { "counters", NULL },
486           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_COUNTERS,
487           .parse = ipset_parse_flag,            .print = ipset_print_flag,
488         },
489         { .name = { "comment", NULL },
490           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_CREATE_COMMENT,
491           .parse = ipset_parse_flag,            .print = ipset_print_flag,
492         },
493         { .name = { "forceadd", NULL },
494           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_FORCEADD,
495           .parse = ipset_parse_flag,            .print = ipset_print_flag,
496         },
497         /* Backward compatibility */
498         { .name = { "probes", NULL },
499           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROBES,
500           .parse = ipset_parse_ignored,         .print = ipset_print_number,
501         },
502         { .name = { "resize", NULL },
503           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_RESIZE,
504           .parse = ipset_parse_ignored,         .print = ipset_print_number,
505         },
506         { .name = { "from", NULL },
507           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
508           .parse = ipset_parse_ignored,
509         },
510         { .name = { "to", NULL },
511           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP_TO,
512           .parse = ipset_parse_ignored,
513         },
514         { .name = { "network", NULL },
515           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
516           .parse = ipset_parse_ignored,
517         },
518         { },
519 };
520
521 static const char hash_ipport_usage4[] =
522 "create SETNAME hash:ip,port\n"
523 "               [family inet|inet6]\n"
524 "               [hashsize VALUE] [maxelem VALUE]\n"
525 "               [timeout VALUE] [counters] [comment]\n"
526 "               [forceadd]\n"
527 "add    SETNAME IP,PROTO:PORT [timeout VALUE]\n"
528 "               [packets VALUE] [bytes VALUE] [comment \"string\"]\n"
529 "del    SETNAME IP,PROTO:PORT\n"
530 "test   SETNAME IP,PROTO:PORT\n\n"
531 "where depending on the INET family\n"
532 "      IP is a valid IPv4 or IPv6 address (or hostname).\n"
533 "      Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
534 "      is supported for IPv4.\n"
535 "      Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
536 "      port range is supported both for IPv4 and IPv6.\n";
537
538 static struct ipset_type ipset_hash_ipport4 = {
539         .name = "hash:ip,port",
540         .alias = { "ipporthash", NULL },
541         .revision = 4,
542         .family = NFPROTO_IPSET_IPV46,
543         .dimension = IPSET_DIM_TWO,
544         .elem = {
545                 [IPSET_DIM_ONE - 1] = {
546                         .parse = ipset_parse_ip4_single6,
547                         .print = ipset_print_ip,
548                         .opt = IPSET_OPT_IP
549                 },
550                 [IPSET_DIM_TWO - 1] = {
551                         .parse = ipset_parse_proto_port,
552                         .print = ipset_print_proto_port,
553                         .opt = IPSET_OPT_PORT
554                 },
555         },
556         .args = {
557                 [IPSET_CREATE] = hash_ipport_create_args4,
558                 [IPSET_ADD] = hash_ipport_add_args3,
559         },
560         .mandatory = {
561                 [IPSET_CREATE] = 0,
562                 [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
563                         | IPSET_FLAG(IPSET_OPT_PROTO)
564                         | IPSET_FLAG(IPSET_OPT_PORT),
565                 [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
566                         | IPSET_FLAG(IPSET_OPT_PROTO)
567                         | IPSET_FLAG(IPSET_OPT_PORT),
568                 [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
569                         | IPSET_FLAG(IPSET_OPT_PROTO)
570                         | IPSET_FLAG(IPSET_OPT_PORT),
571         },
572         .full = {
573                 [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
574                         | IPSET_FLAG(IPSET_OPT_MAXELEM)
575                         | IPSET_FLAG(IPSET_OPT_TIMEOUT)
576                         | IPSET_FLAG(IPSET_OPT_COUNTERS)
577                         | IPSET_FLAG(IPSET_OPT_CREATE_COMMENT)
578                         | IPSET_FLAG(IPSET_OPT_FORCEADD),
579                 [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
580                         | IPSET_FLAG(IPSET_OPT_IP_TO)
581                         | IPSET_FLAG(IPSET_OPT_PORT)
582                         | IPSET_FLAG(IPSET_OPT_PORT_TO)
583                         | IPSET_FLAG(IPSET_OPT_PROTO)
584                         | IPSET_FLAG(IPSET_OPT_TIMEOUT)
585                         | IPSET_FLAG(IPSET_OPT_PACKETS)
586                         | IPSET_FLAG(IPSET_OPT_BYTES)
587                         | IPSET_FLAG(IPSET_OPT_ADT_COMMENT),
588                 [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
589                         | IPSET_FLAG(IPSET_OPT_IP_TO)
590                         | IPSET_FLAG(IPSET_OPT_PORT)
591                         | IPSET_FLAG(IPSET_OPT_PORT_TO)
592                         | IPSET_FLAG(IPSET_OPT_PROTO),
593                 [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
594                         | IPSET_FLAG(IPSET_OPT_PORT)
595                         | IPSET_FLAG(IPSET_OPT_PROTO),
596         },
597
598         .usage = hash_ipport_usage4,
599         .usagefn = ipset_port_usage,
600         .description = "forceadd support",
601 };
602
603 /* Parse commandline arguments */
604 static const struct ipset_arg hash_ipport_create_args5[] = {
605         { .name = { "family", NULL },
606           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_FAMILY,
607           .parse = ipset_parse_family,          .print = ipset_print_family,
608         },
609         /* Alias: family inet */
610         { .name = { "-4", NULL },
611           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_FAMILY,
612           .parse = ipset_parse_family,
613         },
614         /* Alias: family inet6 */
615         { .name = { "-6", NULL },
616           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_FAMILY,
617           .parse = ipset_parse_family,
618         },
619         { .name = { "hashsize", NULL },
620           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_HASHSIZE,
621           .parse = ipset_parse_uint32,          .print = ipset_print_number,
622         },
623         { .name = { "maxelem", NULL },
624           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_MAXELEM,
625           .parse = ipset_parse_uint32,          .print = ipset_print_number,
626         },
627         { .name = { "timeout", NULL },
628           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
629           .parse = ipset_parse_timeout,         .print = ipset_print_number,
630         },
631         { .name = { "counters", NULL },
632           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_COUNTERS,
633           .parse = ipset_parse_flag,            .print = ipset_print_flag,
634         },
635         { .name = { "comment", NULL },
636           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_CREATE_COMMENT,
637           .parse = ipset_parse_flag,            .print = ipset_print_flag,
638         },
639         { .name = { "forceadd", NULL },
640           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_FORCEADD,
641           .parse = ipset_parse_flag,            .print = ipset_print_flag,
642         },
643         { .name = { "skbinfo", NULL },
644           .has_arg = IPSET_NO_ARG,              .opt = IPSET_OPT_SKBINFO,
645           .parse = ipset_parse_flag,            .print = ipset_print_flag,
646         },
647         /* Backward compatibility */
648         { .name = { "probes", NULL },
649           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PROBES,
650           .parse = ipset_parse_ignored,         .print = ipset_print_number,
651         },
652         { .name = { "resize", NULL },
653           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_RESIZE,
654           .parse = ipset_parse_ignored,         .print = ipset_print_number,
655         },
656         { .name = { "from", NULL },
657           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
658           .parse = ipset_parse_ignored,
659         },
660         { .name = { "to", NULL },
661           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP_TO,
662           .parse = ipset_parse_ignored,
663         },
664         { .name = { "network", NULL },
665           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_IP,
666           .parse = ipset_parse_ignored,
667         },
668         { },
669 };
670
671 static const struct ipset_arg hash_ipport_add_args5[] = {
672         { .name = { "timeout", NULL },
673           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_TIMEOUT,
674           .parse = ipset_parse_timeout,         .print = ipset_print_number,
675         },
676         { .name = { "packets", NULL },
677           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_PACKETS,
678           .parse = ipset_parse_uint64,          .print = ipset_print_number,
679         },
680         { .name = { "bytes", NULL },
681           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_BYTES,
682           .parse = ipset_parse_uint64,          .print = ipset_print_number,
683         },
684         { .name = { "comment", NULL },
685           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_ADT_COMMENT,
686           .parse = ipset_parse_comment,         .print = ipset_print_comment,
687         },
688         { .name = { "skbmark", NULL },
689           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_SKBMARK,
690           .parse = ipset_parse_skbmark,         .print = ipset_print_skbmark,
691         },
692         { .name = { "skbprio", NULL },
693           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_SKBPRIO,
694           .parse = ipset_parse_skbprio,         .print = ipset_print_skbprio,
695         },
696         { .name = { "skbqueue", NULL },
697           .has_arg = IPSET_MANDATORY_ARG,       .opt = IPSET_OPT_SKBQUEUE,
698           .parse = ipset_parse_uint16,          .print = ipset_print_number,
699         },
700         { },
701 };
702
703 static const char hash_ipport_usage5[] =
704 "create SETNAME hash:ip,port\n"
705 "               [family inet|inet6]\n"
706 "               [hashsize VALUE] [maxelem VALUE]\n"
707 "               [timeout VALUE] [counters] [comment]\n"
708 "               [forceadd] [skbinfo]\n"
709 "add    SETNAME IP,PROTO:PORT [timeout VALUE]\n"
710 "               [packets VALUE] [bytes VALUE] [comment \"string\"]\n"
711 "               [skbmark VALUE] [skbprio VALUE] [skbqueue VALUE]\n"
712 "del    SETNAME IP,PROTO:PORT\n"
713 "test   SETNAME IP,PROTO:PORT\n\n"
714 "where depending on the INET family\n"
715 "      IP is a valid IPv4 or IPv6 address (or hostname).\n"
716 "      Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
717 "      is supported for IPv4.\n"
718 "      Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
719 "      port range is supported both for IPv4 and IPv6.\n";
720
721 static struct ipset_type ipset_hash_ipport5 = {
722         .name = "hash:ip,port",
723         .alias = { "ipporthash", NULL },
724         .revision = 5,
725         .family = NFPROTO_IPSET_IPV46,
726         .dimension = IPSET_DIM_TWO,
727         .elem = {
728                 [IPSET_DIM_ONE - 1] = {
729                         .parse = ipset_parse_ip4_single6,
730                         .print = ipset_print_ip,
731                         .opt = IPSET_OPT_IP
732                 },
733                 [IPSET_DIM_TWO - 1] = {
734                         .parse = ipset_parse_proto_port,
735                         .print = ipset_print_proto_port,
736                         .opt = IPSET_OPT_PORT
737                 },
738         },
739         .args = {
740                 [IPSET_CREATE] = hash_ipport_create_args5,
741                 [IPSET_ADD] = hash_ipport_add_args5,
742         },
743         .mandatory = {
744                 [IPSET_CREATE] = 0,
745                 [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
746                         | IPSET_FLAG(IPSET_OPT_PROTO)
747                         | IPSET_FLAG(IPSET_OPT_PORT),
748                 [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
749                         | IPSET_FLAG(IPSET_OPT_PROTO)
750                         | IPSET_FLAG(IPSET_OPT_PORT),
751                 [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
752                         | IPSET_FLAG(IPSET_OPT_PROTO)
753                         | IPSET_FLAG(IPSET_OPT_PORT),
754         },
755         .full = {
756                 [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
757                         | IPSET_FLAG(IPSET_OPT_MAXELEM)
758                         | IPSET_FLAG(IPSET_OPT_TIMEOUT)
759                         | IPSET_FLAG(IPSET_OPT_COUNTERS)
760                         | IPSET_FLAG(IPSET_OPT_CREATE_COMMENT)
761                         | IPSET_FLAG(IPSET_OPT_FORCEADD)
762                         | IPSET_FLAG(IPSET_OPT_SKBINFO),
763                 [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
764                         | IPSET_FLAG(IPSET_OPT_IP_TO)
765                         | IPSET_FLAG(IPSET_OPT_PORT)
766                         | IPSET_FLAG(IPSET_OPT_PORT_TO)
767                         | IPSET_FLAG(IPSET_OPT_PROTO)
768                         | IPSET_FLAG(IPSET_OPT_TIMEOUT)
769                         | IPSET_FLAG(IPSET_OPT_PACKETS)
770                         | IPSET_FLAG(IPSET_OPT_BYTES)
771                         | IPSET_FLAG(IPSET_OPT_ADT_COMMENT)
772                         | IPSET_FLAG(IPSET_OPT_SKBMARK)
773                         | IPSET_FLAG(IPSET_OPT_SKBPRIO)
774                         | IPSET_FLAG(IPSET_OPT_SKBQUEUE),
775                 [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
776                         | IPSET_FLAG(IPSET_OPT_IP_TO)
777                         | IPSET_FLAG(IPSET_OPT_PORT)
778                         | IPSET_FLAG(IPSET_OPT_PORT_TO)
779                         | IPSET_FLAG(IPSET_OPT_PROTO),
780                 [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
781                         | IPSET_FLAG(IPSET_OPT_PORT)
782                         | IPSET_FLAG(IPSET_OPT_PROTO),
783         },
784
785         .usage = hash_ipport_usage5,
786         .usagefn = ipset_port_usage,
787         .description = "skbinfo support",
788 };
789
790 void _init(void);
791 void _init(void)
792 {
793         ipset_type_add(&ipset_hash_ipport1);
794         ipset_type_add(&ipset_hash_ipport2);
795         ipset_type_add(&ipset_hash_ipport3);
796         ipset_type_add(&ipset_hash_ipport4);
797         ipset_type_add(&ipset_hash_ipport5);
798 }